libqtaws  0.1.0
UnofficialAWSlibraryforQt-InternalDocumentation
awsendpoint.cpp
1 /*
2  Copyright 2013-2015 Paul Colby
3 
4  This file is part of libqtaws.
5 
6  Libqtaws is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Libqtaws is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with libqtaws. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "awsendpoint.h"
21 #include "awsendpoint_p.h"
22 
23 #include <QDebug>
24 #include <QFile>
25 #include <QMutexLocker>
26 
27 QTAWS_BEGIN_NAMESPACE
28 
29 /**
30  * @class AwsEndpoint
31  *
32  * @brief Provides AWS endpoint information.
33  *
34  * @note This class provides fairly low-level access to AWS endpoint data.
35  * You should consider using the AwsRegion and/or various
36  * AwsService-derived classes in preference to using this class
37  * directly where possible.
38  *
39  * This class parses the `endpoint.xml` data available at
40  * http://aws-sdk-configurations.amazonwebservices.com/endpoints.xml
41  *
42  * The `endpoint.xml` file is embedded as a resource in the libqtaws
43  * library - not fetched remotely at runtime.
44  *
45  * Example usage:
46  * @code
47  * AwsEndpoint endpoint(QLatin1String("cloudformation.us-east-1.amazonaws.com"));
48  *
49  * endpoint.hostName(); // "cloudformation.us-east-1.amazonaws.com"
50  * endpoint.regionName(); // "us-east-1"
51  * endpoint.serviceName(); // "cloudformation"
52  *
53  * endpoint.supportedRegions(); // [ "us-east-1" ]
54  *
55  * endpoint.isSupported(AwsEndpoint::HTTP); // false
56  * endpoint.isSupported(AwsEndpoint::HTTPS); // true
57  *
58  * QUrl ec2 = AwsEndpoint::getEndpoint("ap-southeast-2", "ec2");
59  * QUrl iam = AwsEndpoint::getEndpoint("ap-southeast-2", "iam");
60  *
61  * ec2.host(); // "ec2.ap-southeast-2.amazonaws.com"
62  * iam.host(); // "iam.amazonaws.com"
63  * @endcode
64  *
65  * @see AwsRegion
66  * @see AwsService
67  */
68 
69 /**
70  * @brief Constructs a new AwsEndpoint object.
71  *
72  * @param hostName Name of an AWS host, encoded as UTF-8.
73  */
74 AwsEndpoint::AwsEndpoint(const QByteArray &hostName)
75  : d_ptr(new AwsEndpointPrivate(this))
76 {
77  Q_D(AwsEndpoint);
78  d->hostName = QString::fromUtf8(hostName);
79  QMutexLocker locker(&AwsEndpointPrivate::mutex);
80  if (AwsEndpointPrivate::hosts.contains(d->hostName)) {
81  if (!AwsEndpointPrivate::hosts[d->hostName].regionNames.empty()) {
82  d->regionName = AwsEndpointPrivate::hosts[d->hostName].regionNames.first();
83  }
84  d->serviceName = AwsEndpointPrivate::hosts[d->hostName].serviceName;
85  }
86 }
87 
88 /**
89  * @brief Constructs a new AwsEndpoint object.
90  *
91  * @param hostName Name of an AWS host.
92  */
93 AwsEndpoint::AwsEndpoint(const QString &hostName)
94  : d_ptr(new AwsEndpointPrivate(this))
95 {
96  Q_D(AwsEndpoint);
97  d->hostName = hostName;
98  QMutexLocker locker(&AwsEndpointPrivate::mutex);
99  if (AwsEndpointPrivate::hosts.contains(d->hostName)) {
100  if (!AwsEndpointPrivate::hosts[d->hostName].regionNames.empty()) {
101  d->regionName = AwsEndpointPrivate::hosts[d->hostName].regionNames.first();
102  }
103  d->serviceName = AwsEndpointPrivate::hosts[d->hostName].serviceName;
104  }
105 }
106 
107 /**
108  * @brief AwsEndpoint destructor.
109  */
111 {
112  delete d_ptr;
113 }
114 
115 /**
116  * @brief Get a QUrl for an AWS endpoint.
117  *
118  * This function will return a QUrl object for accessing an AWS service. The
119  * region and service names must match those used by Amazon.
120  *
121  * If the specified region and/or service are not known to be valid for AWS, or
122  * the service is not supported in the specified region, then an invalid QUrl
123  * will be returned.
124  *
125  * @note An invalid QUrl is one for which QUrl::isValid returns `false`.
126  *
127  * The \p transport parameter may be used to specify one or more transports to
128  * consider. If the specified AWS endpoint exists, but does not support //any//
129  * of the given transports, then an invalid QUrl is returned.
130  *
131  * Where it makes sense to do so, the resulting QUrl's scheme will be set
132  * according to the requested transport. For example, if the selected transport
133  * is AwsEndpoint::HTTPS, then the resulting QUrl's schems will be set to
134  * "https".
135  *
136  * If \p transport includes both AwsEndpoint::HTTP //and// AwsEndpoint::HTTPS,
137  * and both are supported by the AWS endpoint, then "https" will be chosed in
138  * preference to "http".
139  *
140  * @note It is possible for the returned QUrl to specify a host that is not
141  * located in, nor dedicated to the specified region. For examepl, if
142  * requesting an endpoint for the `iam` service in `ap-southeast-2`, the
143  * return endpoint is for a host (`iam.amazonaws.com`) which provides
144  * the `ami` services for all regions, not just `ap-southeast-2`.
145  * Services known to behave like this include: `cloudfront`, `iam`,
146  * `importexport`, `route53`, and `sts`.
147  *
148  * Example usage:
149  * @code
150  * QUrl ec2 = AwsEndpoint::getEndpoint("ap-southeast-2", "ec2");
151  * QUrl iam = AwsEndpoint::getEndpoint("ap-southeast-2", "iam");
152  * ec2.host(); // "ec2.ap-southeast-2.amazonaws.com"
153  * iam.host(); // "iam.amazonaws.com"
154  * @endcode
155  *
156  * @param regionName Endpoint's region name.
157  * @param serviceName Endpoint's service name.
158  * @param transport Optional network transport(s) for the endpoint.
159  *
160  * @return A QUrl representing the AWS endpoint, or an invalid QUrl if there
161  * is no such _known_ AWS endpoint.
162  */
163 QUrl AwsEndpoint::getEndpoint(const QString &regionName, const QString &serviceName,
164  const Transports transport)
165 {
167  QMutexLocker locker(&AwsEndpointPrivate::mutex);
168  if ((!AwsEndpointPrivate::regions.contains(regionName)) ||
169  (!AwsEndpointPrivate::regions[regionName].services.contains(serviceName))) {
170  return QUrl();
171  }
172  const AwsEndpointPrivate::RegionEndpointInfo &endpointInfo =
174  if (!(endpointInfo.transports & transport)) {
175  return QUrl();
176  }
177 
178  QUrl url;
179  url.setHost(endpointInfo.hostName);
180  if ((endpointInfo.transports & HTTPS) && (transport & HTTPS))
181  url.setScheme(QLatin1String("https"));
182  else if ((endpointInfo.transports & HTTP) && (transport & HTTP))
183  url.setScheme(QLatin1String("http"));
184  /// @todo Handle SMTP here?
185  return url;
186 }
187 
188 /**
189  * @brief Get the name of host represented by this endpoint.
190  *
191  * @return Name of host represented by this endpoint.
192  */
193 QString AwsEndpoint::hostName() const
194 {
195  Q_D(const AwsEndpoint);
196  return d->hostName;
197 }
198 
199 /**
200  * @brief Is a region / service / transport combination supported by Amazon?
201  *
202  * @param regionName AWS region name to check support for.
203  * @param serviceName AWS service name to check support for.
204  * @param transport Optional transport to check support for.
205  *
206  * @return `true` if the service is supported in the \p regionName region for at least
207  * one of the specified transports, `false` otherwise.
208  */
209 bool AwsEndpoint::isSupported(const QString &regionName, const QString &serviceName, const Transports transport)
210 {
212  QMutexLocker locker(&AwsEndpointPrivate::mutex);
213  return ((AwsEndpointPrivate::regions.contains(regionName)) &&
214  (AwsEndpointPrivate::regions[regionName].services.contains(serviceName)) &&
215  (AwsEndpointPrivate::regions[regionName].services[serviceName].transports & transport));
216 }
217 
218 /**
219  * @brief Is the given transport supported by this endpoint?
220  *
221  * @param transport Transport to check for support for.
222  *
223  * @return `true` if the transport is supported by this endpoint, `false` otherwise.
224  */
225 bool AwsEndpoint::isSupported(const Transport transport) const
226 {
227  return isSupported(regionName(), serviceName(), AwsEndpoint::Transports(transport));
228 }
229 
230 /**
231  * @brief Is this endpoint valid?
232  *
233  * An endpoint is considered valid if the host specified during construction is
234  * a known AWS host, and thus we know what region and service(s) it supports.
235  *
236  * For example:
237  * @code
238  * AwsEndpoint good(QLatin1String("cloudformation.us-east-1.amazonaws.com"));
239  * AwsEndpoint bad(QLatin1String("example.com"));
240  * Q_ASSERT(good.isValid()); // good is valid.
241  * Q_ASSERT(!bad.isValid()); // bad is not.
242  * @endcode
243  *
244  * @return `true` if this endpoint is valid, `false` otherwise.
245  */
247 {
248  return ((!hostName().isEmpty()) && (!regionName().isEmpty()) && (!serviceName().isEmpty()));
249 }
250 
251 /**
252  * @brief Get this endpoint's full service name.
253  *
254  * The full service name is a human-readbale form. For example, the full name for
255  * the `cloudsearch` service is `Amazon CloudSearch`. Likewise, the full name for
256  * the `rds` service is `Amazon Relational Database Service`.
257  *
258  * @return This endpoint's full service name.
259  *
260  * @see serviceName
261  */
263 {
264  return fullServiceName(serviceName());
265 }
266 
267 /**
268  * @brief Get the full name for given service.
269  *
270  * The full service name is a human-readbale form. For example, the full name for
271  * the `cloudsearch` service is `Amazon CloudSearch`. Likewise, the full name for
272  * the `rds` service is `Amazon Relational Database Service`.
273  *
274  * @param serviceName Canonical AWS service name to get the full name of.
275  *
276  * @return This endpoint's full service name.
277  *
278  * @see serviceName
279  */
280 QString AwsEndpoint::fullServiceName(const QString &serviceName)
281 {
283  QMutexLocker locker(&AwsEndpointPrivate::mutex);
284  const QHash<QString, AwsEndpointPrivate::ServiceInfo>::const_iterator
285  service = AwsEndpointPrivate::services.constFind(serviceName);
286  return (service == AwsEndpointPrivate::services.constEnd()) ? QString() : service.value().fullName;
287 }
288 
289 /**
290  * @brief Get this endpoint's _primary_ region name.
291  *
292  * It is possible for a single endpiont to support multuple regions, such as
293  * `iam.amazonaws.com`, which provides the `ami` servive for all (non-government)
294  * regions.
295  *
296  * In these cases, this function returns the primary region in which the service
297  * is located. The AwsEndpoint::supportedRegions function may be used to fetch
298  * the full list of regions this endpoint supports.
299  *
300  * @return This endpoint's region name.
301  *
302  * @see supportedRegions
303  */
304 QString AwsEndpoint::regionName() const
305 {
306  Q_D(const AwsEndpoint);
307  return d->regionName;
308 }
309 
310 /**
311  * @brief Get this endpoint's service name.
312  *
313  * @return This endpoint's service name.
314  *
315  * @see fullServiceName
316  */
318 {
319  Q_D(const AwsEndpoint);
320  return d->serviceName;
321 }
322 
323 /**
324  * @brief Get the full list of regions this endpoint supports.
325  *
326  * Alternatvely, AwsEndpoint::regionName may be used to get this endpoint's
327  * _primary_ region.
328  *
329  * @param transport Optional transport to check for support.
330  *
331  * @return A list of all regions this endpoint supports for //at least one// of
332  * the specified transports.
333  *
334  * @see regionName
335  */
336 QStringList AwsEndpoint::supportedRegions(const Transports transport) const
337 {
338  return supportedRegions(serviceName(), transport);
339 }
340 
341 /**
342  * @brief Get a list of regions that supported for a given service.
343  *
344  * @param serviceName AWS service to get the supported regions for.
345  * @param transport Optional transport(s) to check for support.
346  *
347  * @return A list of AWS regions supported for the given service, for
348  * _at least one_ of the specified transports.
349  */
350 QStringList AwsEndpoint::supportedRegions(const QString &serviceName, const Transports transport)
351 {
353  QMutexLocker locker(&AwsEndpointPrivate::mutex);
354 
355  if (transport == AnyTransport) {
356  return AwsEndpointPrivate::services[serviceName].regionNames;
357  }
358 
359  QStringList regions;
360  foreach (const QString &regionName, AwsEndpointPrivate::services[serviceName].regionNames) {
361  if (AwsEndpointPrivate::regions[regionName].services[serviceName].transports & transport)
362  regions.append(regionName);
363  }
364  return regions;
365 }
366 
367 /**
368  * @brief Get a list of services that support a given region.
369  *
370  * @param regionName AWS region to get the supported services for.
371  * @param transport Optional transport(s) to check for support.
372  *
373  * @return A list of AWS services supported for the given region, for
374  * _at least one_ of the specified transports.
375  */
376 QStringList AwsEndpoint::supportedServices(const QString &regionName, const Transports transport)
377 {
379  QMutexLocker locker(&AwsEndpointPrivate::mutex);
380 
381  if (transport == AnyTransport) {
382  return AwsEndpointPrivate::regions[regionName].services.keys();
383  }
384 
385  QStringList serviceNames;
387  for (AwsEndpointPrivate::RegionServices::const_iterator iter = services.constBegin(); iter != services.constEnd(); ++iter) {
388  if (iter.value().transports & transport)
389  serviceNames.append(iter.key());
390  }
391  return serviceNames;
392 }
393 
394 /**
395  * @internal
396  *
397  * @class AwsEndpointPrivate
398  *
399  * @brief Private implementation for AwsEndpoint.
400  */
401 
402 QHash<QString, AwsEndpointPrivate::HostInfo> AwsEndpointPrivate::hosts; ///< Hash of hostnames to HostInfo.
403 QHash<QString, AwsEndpointPrivate::RegionInfo> AwsEndpointPrivate::regions; ///< Hash of region names to RegionInfo.
404 QHash<QString, AwsEndpointPrivate::ServiceInfo> AwsEndpointPrivate::services; ///< Hash of service names to ServiceInfo.
405 
406 QMutex AwsEndpointPrivate::mutex(QMutex::Recursive); ///< Mutex for protecting access to static members.
407 
408 /**
409  * @internal
410  *
411  * @brief Constructs a new AwsEndpointPrivate object.
412  *
413  * @param q Pointer to this object's public AwsEndpoint instance.
414  *
415  * @see http://aws-sdk-configurations.amazonwebservices.com/endpoints.xml
416  */
418  : q_ptr(q)
419 {
421 }
422 
423 /**
424  * @internal
425  *
426  * @brief Load endpoint data
427  *
428  * This function parses AWS endpoint data in XML format. The XML data is
429  * expected to match the same format as the file provided by Amazon at
430  * http://aws-sdk-configurations.amazonwebservices.com/endpoints.xml
431  *
432  * If _any_ data has been loaded previously, this function will return
433  * immediately with no parsing performed.
434  *
435  * @param fileName Name of the endpoint XML data file to load.
436  */
437 void AwsEndpointPrivate::loadEndpointData(const QString &fileName)
438 {
439  QMutexLocker locker(&mutex);
440  if (!hosts.empty()) {
441  return; // Already loaded.
442  }
443 
444  // Open the data file.
445  QFile file(fileName);
446  loadEndpointData(file);
447 }
448 
449 /**
450  * @internal
451  *
452  * @brief Load endpoint data
453  *
454  * This function parses AWS endpoint data in XML format. The XML data is
455  * expected to match the same format as the file provided by Amazon at
456  * http://aws-sdk-configurations.amazonwebservices.com/endpoints.xml
457  *
458  * If _any_ data has been loaded previously, this function will return
459  * immediately with no parsing performed.
460  *
461  * @param device Device to parse XML data from.
462  */
464 {
465  QMutexLocker locker(&mutex);
466  if (!hosts.empty()) {
467  return; // Already loaded.
468  }
469 
470  // Open the device, if not already open.
471  if ((!device.isOpen()) && (!device.open(QIODevice::ReadOnly))) {
472  qWarning() << "AwsEndpoint:" << device.errorString();
473  return;
474  }
475 
476  // Parse the data.
477  QXmlStreamReader xml(&device);
478  loadEndpointData(xml);
479 }
480 
481 /**
482  * @internal
483  *
484  * @brief Load endpoint data
485  *
486  * This function parses AWS endpoint data in XML format. The XML data is
487  * expected to match the same format as the file provided by Amazon at
488  * http://aws-sdk-configurations.amazonwebservices.com/endpoints.xml
489  *
490  * If _any_ data has been loaded previously, this function will return
491  * immediately with no parsing performed.
492  *
493  * @param xml XML document to parse.
494  */
495 void AwsEndpointPrivate::loadEndpointData(QXmlStreamReader &xml)
496 {
497  QMutexLocker locker(&mutex);
498  if (!hosts.empty()) {
499  return; // Already loaded.
500  }
501 
502  // Parse the XML data.
503  while (xml.readNextStartElement()) {
504  if (xml.name() == QLatin1String("Regions")) {
505  parseRegions(xml);
506  } else if (xml.name() == QLatin1String("Services")) {
507  parseServices(xml);
508  } else if (xml.name() != QLatin1String("XML")) {
509  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
510  }
511  }
512  if (xml.hasError()) {
513  qWarning() << "AwsEndpoint:" << xml.errorString();
514  }
515  Q_ASSERT(!xml.hasError());
516  Q_ASSERT(!hosts.isEmpty());
517  Q_ASSERT(!regions.isEmpty());
518  Q_ASSERT(!services.isEmpty());
519 }
520 
521 /**
522  * @internal
523  *
524  * @brief Parse a `Region` element from Amazon's endpoint XML data
525  *
526  * This function parses XML elements like:
527  *
528  * @code{xml}
529  * <Region>
530  * <Name>us-east-1</Name>
531  * <Endpoint>
532  * <ServiceName>cloudformation</ServiceName>
533  * <Http>false</Http>
534  * <Https>true</Https>
535  * <Hostname>cloudformation.us-east-1.amazonaws.com</Hostname>
536  * </Endpoint>
537  * <Endpoint>
538  * <ServiceName>cloudfront</ServiceName>
539  * <Http>true</Http>
540  * <Https>true</Https>
541  * <Hostname>cloudfront.amazonaws.com</Hostname>
542  * </Endpoint>
543  * </Region>
544  * @endcode
545  *
546  * The parsed entries are automatically added to AwsEndpointPrivate::hosts
547  * and AwsEndpointPrivate::regions.
548  *
549  * @param xml XML element to parse.
550  *
551  * @see parseRegion
552  */
553 void AwsEndpointPrivate::parseRegion(QXmlStreamReader &xml)
554 {
555  QString regionName;
556  while ((!xml.atEnd()) && (xml.readNextStartElement())) {
557  if (xml.name() == QLatin1String("Name")) {
558  regionName = xml.readElementText();
559  } else if (xml.name() == QLatin1String("Endpoint")) {
560  Q_ASSERT(!regionName.isEmpty());
561  RegionEndpointInfo endpoint;
562  QString serviceName;
563  while ((!xml.atEnd()) && (xml.readNextStartElement())) {
564  if (xml.name() == QLatin1String("ServiceName")) {
565  serviceName = xml.readElementText();
566  } else if (xml.name() == QLatin1String("Http")) {
567  if (xml.readElementText() == QLatin1String("true")) {
568  endpoint.transports |= AwsEndpoint::HTTP;
569  }
570  } else if (xml.name() == QLatin1String("Https")) {
571  if (xml.readElementText() == QLatin1String("true")) {
572  endpoint.transports |= AwsEndpoint::HTTPS;
573  }
574  } else if (xml.name() == QLatin1String("Hostname")) {
575  endpoint.hostName = xml.readElementText();
576  } else {
577  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
578  xml.skipCurrentElement();
579  }
580  }
581  Q_ASSERT(!serviceName.isEmpty());
582 
583  if (serviceName == QLatin1String("email")) {
584  endpoint.transports |= AwsEndpoint::SMTP;
585  }
586 
587  Q_ASSERT((!hosts.contains(endpoint.hostName)) || (hosts.value(endpoint.hostName).serviceName == serviceName));
588  hosts[endpoint.hostName].regionNames.append(regionName);
589  hosts[endpoint.hostName].serviceName = serviceName;
590  regions[regionName].services[serviceName] = endpoint;
591  //qDebug() << Q_FUNC_INFO << regionName << serviceName << (int)endpoint.transports << endpoint.hostName;
592  } else {
593  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
594  xml.skipCurrentElement();
595  }
596  }
597 }
598 
599 /**
600  * @internal
601  *
602  * @brief Parse a `Regions` element from Amazon's endpoint XML data
603  *
604  * This function parse an XML element containing a list of `Region` elements.
605  * See AwsEndpointPrivate::parseRegion for the `Region` element format.
606  *
607  * The parsed entries are automatically added to AwsEndpointPrivate::hosts
608  * and AwsEndpointPrivate::regions.
609  *
610  * @param xml XML element containing regions to parse.
611  *
612  * @see parseRegion
613  */
614 void AwsEndpointPrivate::parseRegions(QXmlStreamReader &xml)
615 {
616  while ((!xml.atEnd()) && (xml.readNextStartElement())) {
617  if (xml.name() == QLatin1String("Region")) {
618  parseRegion(xml);
619  } else {
620  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
621  xml.skipCurrentElement();
622  }
623  }
624 }
625 
626 /**
627  * @internal
628  *
629  * @brief Parse a `Service` element from Amazon's endpoint XML data
630  *
631  * This function parses XML elements like:
632  *
633  * @code{xml}
634  * <Service>
635  * <Name>cloudformation</Name>
636  * <FullName>Amazon CloudFormation</FullName>
637  * <RegionName>us-east-1</RegionName>
638  * <RegionName>us-west-1</RegionName>
639  * <RegionName>us-west-2</RegionName>
640  * <RegionName>eu-west-1</RegionName>
641  * <RegionName>ap-northeast-1</RegionName>
642  * <RegionName>ap-southeast-1</RegionName>
643  * <RegionName>ap-southeast-2</RegionName>
644  * <RegionName>sa-east-1</RegionName>
645  * </Service>
646  * @endcode
647  *
648  * The parsed entries are automatically added to AwsEndpointPrivate::services.
649  *
650  * @param xml XML element to parse.
651  *
652  * @see parseServices
653  */
654 void AwsEndpointPrivate::parseService(QXmlStreamReader &xml)
655 {
656  QString serviceName;
657  while ((!xml.atEnd()) && (xml.readNextStartElement())) {
658  if (xml.name() == QLatin1String("Name")) {
659  serviceName = xml.readElementText();
660  } else if (xml.name() == QLatin1String("FullName")) {
661  Q_ASSERT(!serviceName.isEmpty());
662  services[serviceName].fullName = xml.readElementText();
663  } else if (xml.name() == QLatin1String("RegionName")) {
664  Q_ASSERT(!serviceName.isEmpty());
665  const QString &regionName = xml.readElementText();
666  services[serviceName].regionNames.append(regionName);
667  //qDebug() << Q_FUNC_INFO << serviceName << services[serviceName].fullName << regionName;
668  } else {
669  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
670  xml.skipCurrentElement();
671  }
672  }
673 }
674 
675 /**
676  * @internal
677  *
678  * @brief Parse a `Services` element from Amazon's endpoint XML data
679  *
680  * This function parses an XML element containing a list of `Service` elements.
681  * See AwsEndpointPrivate::parseServices for the `Service` element format.
682  *
683  * The parsed entries are automatically added to AwsEndpointPrivate::services.
684  *
685  * @param xml XML element containing services to parse.
686  *
687  * @see parseService
688  */
689 void AwsEndpointPrivate::parseServices(QXmlStreamReader &xml)
690 {
691  while ((!xml.atEnd()) && (xml.readNextStartElement())) {
692  if (xml.name() == QLatin1String("Service")) {
693  parseService(xml);
694  } else {
695  qDebug() << Q_FUNC_INFO << "ignoring" << xml.name();
696  xml.skipCurrentElement();
697  }
698  }
699 }
700 
701 QTAWS_END_NAMESPACE
AwsEndpoint(const QByteArray &hostName)
Constructs a new AwsEndpoint object.
Definition: awsendpoint.cpp:74
AwsEndpointPrivate(AwsEndpoint *const q)
Constructs a new AwsEndpointPrivate object.
QString hostName() const
Get the name of host represented by this endpoint.
bool isValid() const
Is this endpoint valid?
static QMutex mutex
Mutex for protecting access to static members.
Definition: awsendpoint_p.h:77
static QStringList supportedServices(const QString &regionName, const Transports transport=AnyTransport)
Get a list of services that support a given region.
Transport
Network transport supported by one or more AWS endpoints.
Definition: awsendpoint.h:37
QString fullServiceName() const
Get this endpoint's full service name.
QHash< QString, RegionEndpointInfo > RegionServices
Hash of service names to RegionEndpointInfo.
Definition: awsendpoint_p.h:60
QString serviceName() const
Get this endpoint's service name.
static QHash< QString, RegionInfo > regions
Hash of region names to RegionInfo.
Definition: awsendpoint_p.h:74
QString regionName
This endpoint's region name.
Definition: awsendpoint_p.h:41
QStringList supportedRegions(const Transports transport=AnyTransport) const
Get the full list of regions this endpoint supports.
QString regionName() const
Get this endpoint's primary region name.
Provides AWS endpoint information.
Definition: awsendpoint.h:33
AwsEndpoint::Transports transports
Transports supported by this AWS endpoint.
Definition: awsendpoint_p.h:56
QString serviceName
This endpoint's service name.
Definition: awsendpoint_p.h:42
static void parseServices(QXmlStreamReader &xml)
Parse a Services element from Amazon's endpoint XML data.
static void loadEndpointData(const QString &fileName=QLatin1String(":/aws/endpoints.xml"))
Load endpoint data.
AwsEndpointPrivate *const d_ptr
Internal d-pointer.
Definition: awsendpoint.h:79
static bool isSupported(const QString &regionName, const QString &serviceName, const Transports transport=AnyTransport)
Is a region / service / transport combination supported by Amazon?
static void parseRegion(QXmlStreamReader &xml)
Parse a Region element from Amazon's endpoint XML data.
Private implementation for AwsEndpoint.
Definition: awsendpoint_p.h:37
~AwsEndpoint()
AwsEndpoint destructor.
static QUrl getEndpoint(const QString &regionName, const QString &serviceName, const Transports transport=AnyTransport)
Get a QUrl for an AWS endpoint.
static QHash< QString, ServiceInfo > services
Hash of service names to ServiceInfo.
Definition: awsendpoint_p.h:75
QString hostName
AWS endpoint's hostname.
Definition: awsendpoint_p.h:55
The per-region endpoint-specific information to load from the endpoints.xml file. ...
Definition: awsendpoint_p.h:54
static void parseRegions(QXmlStreamReader &xml)
Parse a Regions element from Amazon's endpoint XML data.
static QHash< QString, HostInfo > hosts
Hash of hostnames to HostInfo.
Definition: awsendpoint_p.h:73
static void parseService(QXmlStreamReader &xml)
Parse a Service element from Amazon's endpoint XML data.