WMSClient.cpp
Go to the documentation of this file.
1 #include "WMSClient.h"
2 
3 // TerraLib
4 #include "../../../../core/filesystem/FileSystem.h"
5 #include "../../../../core/translator/Translator.h"
6 #include "../../../core/CurlWrapper.h"
7 #include "../../../core/Utils.h"
8 #include "../../../core/Exception.h"
9 #include "WMSClient.h"
11 
12 // Boost
13 #include <boost/filesystem.hpp>
14 #include <boost/lexical_cast.hpp>
15 
16 #include <string>
17 
18 te::ws::ogc::WMSClient::WMSClient(const std::string usrDataDir, const std::string uri, const std::string version) :
19  m_version(version),
20  m_uri(uri)
21 {
22  m_dataDir = usrDataDir + "/wms/";
23 
24  m_curl = std::shared_ptr<te::ws::core::CurlWrapper>(new te::ws::core::CurlWrapper());
25 
26  if(!m_uri.user().empty() && !m_uri.password().empty())
27  {
28  m_curl->setAuthenticationMethod(te::ws::core::HTTP_BASIC);
29  m_curl->setUsername(m_uri.user());
30  m_curl->setPassword(m_uri.password());
31  }
32 
33  std::string baseUrl = m_uri.scheme() + "://" + m_uri.host();
34 
35  if (!m_uri.port().empty())
36  {
37  baseUrl = baseUrl + ":" + m_uri.port();
38  }
39 
40  baseUrl = baseUrl + m_uri.path() + "?";
41 
42  if (!m_uri.query().empty())
43  {
44  std::string query = m_uri.query();
45 
46  size_t endsWith = query.rfind("&");
47 
48  if (endsWith != (query.size() - 1))
49  {
50  query.append("&");
51  }
52 
53  baseUrl = baseUrl + query;
54  }
55 
56  m_uri = te::core::URI(baseUrl);
57 
60 
62 
63 }
64 
66 
68 {
69  std::string url = m_uri.uri();
70 
71  url = url + "SERVICE=WMS" + "&VERSION=" + m_version + "&REQUEST=GetCapabilities";
72 
73  m_curl->setTaskMessage(TE_TR("Getting Capabilities"));
74 
75  // Request the WMS Capabilities XML file
76  std::string xmlPath = this->makeFileRequest(url, "capabilities.xml");
77 
78  try
79  {
80  // Parse the XML file into a struct
81  m_capabilities = m_parser->parseCapabilities(xmlPath);
82  }
84  {
85  /*!
86  According to version negotiation, the client must try to request with
87  the higher supported version. If server response with an other version,
88  client must try to request with an lower version.
89  */
90  if (m_version == "1.3.0")
91  {
92  m_version = "1.1.1";
94  this->updateCapabilities();
95  }
96  else if (m_version == "1.1.1")
97  {
98  throw te::ws::core::UnsupportedVersionException() << te::ErrorDescription(TE_TR("Unsupported WMS response version!"));
99  }
100  }
102  {
103  throw;
104  }
105 
106 }
107 
109 {
110  return m_capabilities;
111 }
112 
114 {
116 }
117 
119 {
121 
122  std::string url = this->buildGetMapRequestURL(request);
123 
124  te::core::URI wmsRequest (url);
125 
126  std::string buffer;
127 
128  m_curl->get(wmsRequest, buffer);
129 
130  response.m_buffer = buffer;
131  response.m_size = static_cast<int>(buffer.size());
132  response.m_format = request.m_format;
133 
134  return response;
135 }
136 
137 const std::string te::ws::ogc::WMSClient::saveGetMap(const te::ws::ogc::wms::WMSGetMapRequest &request, const std::string &filename)
138 {
139 
140  std::string url = this->buildGetMapRequestURL(request);
141 
142  std::string path = this->makeFileRequest(url, filename);
143 
144  return path;
145 }
146 
148 {
149 
151 
152  std::string url = this->buildGetFeatureInfoURL(request);
153 
154  te::core::URI wmsRequest (url);
155 
156  std::string buffer;
157 
158  m_curl->get(wmsRequest, buffer);
159 
160  response.m_featureInfoContent = buffer;
161  response.m_infoFormat = request.m_infoFormat;
162 
163  return response;
164 }
165 
166 std::string te::ws::ogc::WMSClient::makeFileRequest(const std::string url, const std::string fileName) const
167 {
168  std::string path = m_dataDir + fileName;
169 
170  m_curl->downloadFile(url, path);
171 
172  return path;
173 }
174 
176 {
177  m_curl.reset(curlWrapper);
178 }
179 
181 {
182 
183  //Sets base URL
184  std::string url;
185 
186  if(m_version == "1.3.0")
187  {
188  url = this->build130GetMapRequestURL(request);
189  }
190  else if (m_version == "1.1.1")
191  {
192  url = this->build111GetMapRequestURL(request);
193  }
194 
195  return url;
196 }
197 
199 {
200  //Sets base URL
201  std::string url = m_uri.uri();
202 
203  url = url + "SERVICE=WMS" + "&VERSION=" + m_version + "&REQUEST=GetMap";
204 
205  if(request.m_layers.size() > 0)
206  {
207  url += "&LAYERS=";
208 
209  for(size_t i = 0; i < request.m_layers.size(); i++)
210  {
211  url += request.m_layers[i];
212 
213  if(i != request.m_layers.size() - 1)
214  {
215  url += ",";
216  }
217  }
218  }
219 
220  if(request.m_styles.size() > 0)
221  {
222  url += "&STYLES=";
223 
224  for(size_t i = 0; i < request.m_styles.size(); i++)
225  {
226  url += request.m_styles[i];
227 
228  if(i != request.m_styles.size() - 1)
229  {
230  url += ",";
231  }
232  }
233  }
234 
235  if(!request.m_srs.empty())
236  {
237  url += "&CRS=" + request.m_srs;
238  }
239 
240  bool isInverted = te::ws::core::IsInvertedEPSG(request.m_srs);
241 
242  if(isInverted)
243  {
244  url += "&BBOX=";
245  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minY);
246  url += ",";
247  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minX);
248  url += ",";
249  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxY);
250  url += ",";
251  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxX);
252  }
253  else
254  {
255  url += "&BBOX=";
256  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minX);
257  url += ",";
258  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minY);
259  url += ",";
260  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxX);
261  url += ",";
262  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxY);
263  }
264 
265 
266 
267  url += "&WIDTH=" + boost::lexical_cast<std::string>(request.m_width);
268  url += "&HEIGHT=" + boost::lexical_cast<std::string>(request.m_height);
269 
270  url += "&FORMAT=" + request.m_format;
271 
272  if(request.m_transparent)
273  {
274  url += "&TRANSPARENT=TRUE";
275  }
276 
277  if(!request.m_bgColor.empty())
278  {
279  url += "&BGCOLOR=" + request.m_bgColor;
280  }
281 
282  if(!request.m_time.empty())
283  {
284  url += "&TIME=" + request.m_time;
285  }
286 
287  return url;
288 }
289 
291 {
292  //Sets base URL
293  std::string url = m_uri.uri();
294 
295 
296  url = url + "SERVICE=WMS" + "&VERSION=" + m_version + "&REQUEST=GetMap";
297 
298  if(request.m_layers.size() > 0)
299  {
300  url += "&LAYERS=";
301 
302  for(size_t i = 0; i < request.m_layers.size(); i++)
303  {
304  url += request.m_layers[i];
305 
306  if(i != request.m_layers.size() - 1)
307  {
308  url += ",";
309  }
310  }
311  }
312 
313  if(request.m_styles.size() > 0)
314  {
315  url += "&STYLES=";
316 
317  for(size_t i = 0; i < request.m_styles.size(); i++)
318  {
319  url += request.m_styles[i];
320 
321  if(i != request.m_styles.size() - 1)
322  {
323  url += ",";
324  }
325  }
326  }
327 
328  if(!request.m_srs.empty())
329  {
330  url += "&SRS=" + request.m_srs;
331  }
332 
333  url += "&BBOX=";
334  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minX);
335  url += ",";
336  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_minY);
337  url += ",";
338  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxX);
339  url += ",";
340  url += boost::lexical_cast<std::string>(request.m_boundingBox.m_maxY);
341 
342 
343  url += "&WIDTH=" + boost::lexical_cast<std::string>(request.m_width);
344  url += "&HEIGHT=" + boost::lexical_cast<std::string>(request.m_height);
345 
346  url += "&FORMAT=" + request.m_format;
347 
348  if(request.m_transparent)
349  {
350  url += "&TRANSPARENT=TRUE";
351  }
352 
353  if(!request.m_bgColor.empty())
354  {
355  url += "&BGCOLOR=" + request.m_bgColor;
356  }
357 
358  if(!request.m_time.empty())
359  {
360  url += "&TIME=" + request.m_time;
361  }
362 
363  return url;
364 }
365 
367 {
368  //Sets base URL
369  std::string url;
370 
371  if(m_version == "1.3.0")
372  {
373  url = this->build130GetFeatureInfoURL(request);
374  }
375  else if (m_version == "1.1.1")
376  {
377  url = this->build111GetFeatureInfoURL(request);
378  }
379 
380  return url;
381 }
382 
384 {
385  //Sets base URL
386  std::string url = m_uri.uri();
387 
388  url = url + "SERVICE=WMS" + "&VERSION=" + m_version + "&REQUEST=GetFeatureInfo";
389 
390  if(request.m_getMap.m_layers.size() > 0)
391  {
392  url += "&LAYERS=";
393 
394  for(size_t i = 0; i < request.m_getMap.m_layers.size(); i++)
395  {
396  url += request.m_getMap.m_layers[i];
397 
398  if(i != request.m_getMap.m_layers.size() - 1)
399  {
400  url += ",";
401  }
402  }
403  }
404 
405  if(request.m_getMap.m_styles.size() > 0)
406  {
407  url += "&STYLES=";
408 
409  for(size_t i = 0; i < request.m_getMap.m_styles.size(); i++)
410  {
411  url += request.m_getMap.m_styles[i];
412 
413  if(i != request.m_getMap.m_styles.size() - 1)
414  {
415  url += ",";
416  }
417  }
418  }
419 
420  if(!request.m_getMap.m_srs.empty())
421  {
422  url += "&CRS=" + request.m_getMap.m_srs;
423  }
424 
425  bool isInverted = te::ws::core::IsInvertedEPSG(request.m_getMap.m_srs);
426 
427  if(isInverted)
428  {
429  url += "&BBOX=";
430  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minY);
431  url += ",";
432  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minX);
433  url += ",";
434  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxY);
435  url += ",";
436  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxX);
437  }
438  else
439  {
440  url += "&BBOX=";
441  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minX);
442  url += ",";
443  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minY);
444  url += ",";
445  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxX);
446  url += ",";
447  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxY);
448  }
449 
450  url += "&WIDTH=" + boost::lexical_cast<std::string>(request.m_getMap.m_width);
451  url += "&HEIGHT=" + boost::lexical_cast<std::string>(request.m_getMap.m_height);
452 
453  if(request.m_queryLayers.size() > 0)
454  {
455  url += "&QUERY_LAYERS=";
456 
457  for(size_t i = 0; i < request.m_queryLayers.size(); i++)
458  {
459  url += request.m_queryLayers[i];
460 
461  if(i != request.m_queryLayers.size() - 1)
462  {
463  url += ",";
464  }
465  }
466  }
467 
468  if(!request.m_infoFormat.empty())
469  {
470  url += "&INFO_FORMAT=" + request.m_infoFormat;
471  }
472 
473  url += "&FEATURE_COUNT=" + boost::lexical_cast<std::string>(request.m_featureCount);
474 
475  url += "&i=" + boost::lexical_cast<std::string>(request.m_i);
476  url += "&j=" + boost::lexical_cast<std::string>(request.m_j);
477 
478  if(!request.m_exceptions.empty())
479  {
480  url += "&EXCEPTIONS=" + request.m_exceptions;
481  }
482 
483  return url;
484 }
485 
487 {
488  //Sets base URL
489  std::string url = m_uri.uri();
490 
491  url = url + "SERVICE=WMS" + "&VERSION=" + m_version + "&REQUEST=GetFeatureInfo";
492 
493  if(request.m_getMap.m_layers.size() > 0)
494  {
495  url += "&LAYERS=";
496 
497  for(size_t i = 0; i < request.m_getMap.m_layers.size(); i++)
498  {
499  url += request.m_getMap.m_layers[i];
500 
501  if(i != request.m_getMap.m_layers.size() - 1)
502  {
503  url += ",";
504  }
505  }
506  }
507 
508  if(request.m_getMap.m_styles.size() > 0)
509  {
510  url += "&STYLES=";
511 
512  for(size_t i = 0; i < request.m_getMap.m_styles.size(); i++)
513  {
514  url += request.m_getMap.m_styles[i];
515 
516  if(i != request.m_getMap.m_styles.size() - 1)
517  {
518  url += ",";
519  }
520  }
521  }
522 
523  if(!request.m_getMap.m_srs.empty())
524  {
525  url += "&SRS=" + request.m_getMap.m_srs;
526  }
527 
528 
529  url += "&BBOX=";
530  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minX);
531  url += ",";
532  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_minY);
533  url += ",";
534  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxX);
535  url += ",";
536  url += boost::lexical_cast<std::string>(request.m_getMap.m_boundingBox.m_maxY);
537 
538  url += "&WIDTH=" + boost::lexical_cast<std::string>(request.m_getMap.m_width);
539  url += "&HEIGHT=" + boost::lexical_cast<std::string>(request.m_getMap.m_height);
540 
541  if(request.m_queryLayers.size() > 0)
542  {
543  url += "&QUERY_LAYERS=";
544 
545  for(size_t i = 0; i < request.m_queryLayers.size(); i++)
546  {
547  url += request.m_queryLayers[i];
548 
549  if(i != request.m_queryLayers.size() - 1)
550  {
551  url += ",";
552  }
553  }
554  }
555 
556  if(!request.m_infoFormat.empty())
557  {
558  url += "&INFO_FORMAT=" + request.m_infoFormat;
559  }
560 
561  url += "&FEATURE_COUNT=" + boost::lexical_cast<std::string>(request.m_featureCount);
562 
563  url += "&X=" + boost::lexical_cast<std::string>(request.m_i);
564  url += "&Y=" + boost::lexical_cast<std::string>(request.m_j);
565 
566  if(!request.m_exceptions.empty())
567  {
568  url += "&EXCEPTIONS=" + request.m_exceptions;
569  }
570 
571  return url;
572 }
std::string path() const
Retrieving the path.
Definition: URI.cpp:118
void setCurlWrapper(te::ws::core::CurlWrapper *curlWrapper)
Sets the TerraLib CurlWrapper to be used internally.
Definition: WMSClient.cpp:175
std::string buildGetFeatureInfoURL(const te::ws::ogc::wms::WMSGetFeatureInfoRequest &request) const
Definition: WMSClient.cpp:366
const te::ws::ogc::wms::WMSGetMapResponse getMap(const te::ws::ogc::wms::WMSGetMapRequest &request) const
Return the WMSGetMapResponse member.
Definition: WMSClient.cpp:118
std::string scheme() const
Retrieving the scheme.
Definition: URI.cpp:93
static bool exists(const std::string &path)
Checks if a given path in UTF-8 exists.
Definition: FileSystem.cpp:142
const te::ws::ogc::wms::WMSCapabilities & getCapabilities() const
Return the WMSCapabilities member.
Definition: WMSClient.cpp:108
static bool isDirectory(const std::string &path)
Checks if a given path in UTF-8 is a directory.
Definition: FileSystem.cpp:87
std::string build111GetFeatureInfoURL(const te::ws::ogc::wms::WMSGetFeatureInfoRequest &request) const
Definition: WMSClient.cpp:486
static bool createDirectories(const std::string &path)
Creates a directory for any element of path that does not exist.
Definition: FileSystem.cpp:153
std::unique_ptr< te::ws::ogc::wms::XMLParser > m_parser
Definition: WMSClient.h:156
te::ws::ogc::wms::WMSCapabilities m_capabilities
Definition: WMSClient.h:154
~WMSClient()
Default destructor.
std::string password() const
Retrieving the password information.
Definition: URI.cpp:103
TEWSCOREEXPORT bool IsInvertedEPSG(const std::string &epsg)
This function gets true for EPSGs that has inverted axis-order. Otherwise false. This implementation ...
te::core::URI m_uri
Definition: WMSClient.h:153
std::string makeFileRequest(const std::string url, const std::string fileName) const
Executes a request on a WMS server.
Definition: WMSClient.cpp:166
This is the abstraction factory for WMS XMLParser.
An abstraction to Lib Curl functions.
Definition: CurlWrapper.h:61
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
std::string m_version
Definition: WMSClient.h:151
std::string query() const
Retrieving the query.
Definition: URI.cpp:123
boost::error_info< struct tag_error_description, std::string > ErrorDescription
The base type for error report messages.
The Capability WMS 1.3.0 struct.
te::da::DataSourceCapabilities capabilities
WMSClient(const std::string usrDataDir="", const std::string uri="", const std::string version="1.3.0")
Class constructor. It initializes the m_uri and m_version class members.
Definition: WMSClient.cpp:18
std::string m_dataDir
Definition: WMSClient.h:152
The WMSGetFeatureInfoRequest WMS 1.3.0 struct.
std::string port() const
Retrieving the port.
Definition: URI.cpp:113
The WMSGetMapResponse WMS 1.3.0 struct.
The WMSGetMapResponse WMS 1.3.0 struct.
std::string host() const
Retrieving the host.
Definition: URI.cpp:108
const std::string saveGetMap(const te::ws::ogc::wms::WMSGetMapRequest &request, const std::string &filename)
It execute a WMS GetMap and save the result image on disk. The request will be based on WMSGetMapRequ...
Definition: WMSClient.cpp:137
void setCapabilities(const te::ws::ogc::wms::WMSCapabilities &capabilities)
Definition: WMSClient.cpp:113
std::string buildGetMapRequestURL(const te::ws::ogc::wms::WMSGetMapRequest &request) const
Definition: WMSClient.cpp:180
const std::string & uri() const
Retrieving the full URI.
Definition: URI.cpp:88
static XMLParser * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
const te::ws::ogc::wms::WMSGetFeatureInfoResponse getFeatureInfo(const te::ws::ogc::wms::WMSGetFeatureInfoRequest &request) const
It execute a WMS GetFeatureInfo and returns a WMSGetFeatureInfoResponse with the result.
Definition: WMSClient.cpp:147
Base exception class for WS Core Runtime Library.
std::string build111GetMapRequestURL(const te::ws::ogc::wms::WMSGetMapRequest &request) const
Definition: WMSClient.cpp:290
A class for representing an Uniform Resource Identifier (URI).
Definition: URI.h:49
std::string build130GetFeatureInfoURL(const te::ws::ogc::wms::WMSGetFeatureInfoRequest &request) const
Definition: WMSClient.cpp:383
Exception to be used when a XML has an unsupported version by WMSClient or WCSClient.
void updateCapabilities()
Method to get the capabilities from a WMS server and store in m_capabilities member.
Definition: WMSClient.cpp:67
std::shared_ptr< te::ws::core::CurlWrapper > m_curl
Definition: WMSClient.h:155
Exception to be used when a XML has an unsupported version by XMLParser.
std::string build130GetMapRequestURL(const te::ws::ogc::wms::WMSGetMapRequest &request) const
Definition: WMSClient.cpp:198
std::string user() const
Retrieving the user information.
Definition: URI.cpp:98
The WMSGetMapRequest WMS 1.3.0 struct.