OWS.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. import urlparse
  4. import urllib
  5. from lxml import objectify
  6. import os,sys
  7. import tempfile
  8. import logging
  9. import ConfigParser
  10. import md5
  11. import mapscript
  12. from string import Template
  13. from osgeo import osr
  14. from osgeo import ogr
  15. class OWS:
  16. capabilities = None
  17. url = None
  18. requestUrl = None
  19. mapobj = None
  20. qstring = None
  21. owsns11 = "http://www.opengis.net/ows/1.1"
  22. owsns = "http://www.opengis.net/ows"
  23. cachedir = None
  24. mapfileName = "mapfile.map"
  25. config = None
  26. parsedUrl = None
  27. service = None
  28. mapfilename = None
  29. def __init__(self,url=None,qstring=None,configFile=None):
  30. self.requestUrl = url
  31. if url:
  32. self.url = url
  33. self.__getCapabilities()
  34. if qstring:
  35. self.qstring = qstring
  36. configFiles = [
  37. os.path.join(os.path.dirname(__file__),"config.cfg")
  38. ]
  39. if sys.platform == "win32":
  40. pass # TODO Default conf. file on windows platform
  41. elif sys.platform == "linux2":
  42. configFiles.append("/etc/owsviewer.cfg")
  43. if configFile:
  44. configFiles.append(configFile)
  45. self.config = ConfigParser.ConfigParser()
  46. self.config.read(configFiles)
  47. logging.debug("Creating cachedir for %s in %s" % (self.url,self.config.get("OWSProxy","cachedir")))
  48. logging.debug("%s initialized"%self.service)
  49. def __getCapabilities(self):
  50. self.parsedUrl = urlparse.urlparse(self.url)
  51. if self.service == "WFS":
  52. from owslib.wfs import WebFeatureService
  53. self.capabilities = WebFeatureService(url=self.url)
  54. elif self.service == "WCS":
  55. from owslib.wcs import WebCoverageService
  56. self.capabilities = WebCoverageService(url=self.url,version="1.0.0")
  57. def getParams(self):
  58. return urlparse.parse_qs(self.qstring)
  59. def getOnlineResource(self,onlineresource,mapfilename=None):
  60. o = urlparse.urlparse(onlineresource)
  61. params = urlparse.parse_qs(o.query,keep_blank_values=True)
  62. params["owsUrl"] = self.url
  63. params["owsService"] = self.service
  64. params["map"] = self.getMapfileLocation(mapfilename)
  65. location = urlparse.urlunparse((o[0],o[1],o[2],o[3],urllib.urlencode(params,True),o[5]))
  66. logging.debug("Setting OnlineResource to %s"% location)
  67. return location
  68. def getMapfileLocation(self,mapfilename=None):
  69. # save the map if possible
  70. if mapfilename:
  71. mapfilename.replace("..","") # remove potential path change
  72. # mapfile must end with .map and cachedir must be at the
  73. # beginning of the mapfile name
  74. if mapfilename.endswith(".map") and \
  75. mapfilename.find(self.cachedir) == 0:
  76. return mapfilename
  77. else:
  78. # do not save anything
  79. return
  80. # save to new location otherwice
  81. else:
  82. return os.path.join(self.cachedir,self.mapfileName)
  83. def __getCacheDir(self):
  84. self.cachedir = tempfile.mkdtemp(prefix="%s-%s"%(self.service,
  85. md5.new(self.url).hexdigest()),
  86. dir=self.config.get("OWSProxy","cachedir"))
  87. os.chmod(self.cachedir, 0777)
  88. logging.debug("Cachedir %s created" % self.cachedir)
  89. open(os.path.join(self.cachedir,"url.txt"),"w").write(self.url)
  90. return self.cachedir
  91. def performRequest(self):
  92. request = mapscript.OWSRequest()
  93. request.loadParams()
  94. mapobj = None
  95. self.request=request.getValueByName("REQUEST")
  96. # if no 'map' parameter in URL, create new mapfile
  97. if not request.getValueByName("map"):
  98. logging.debug("Creating new mapfile")
  99. mapobj = self.makeMap()
  100. else:
  101. # there is 'map' parameter in URL and the file exists, load it
  102. logging.debug("Using existing mapfile %s" % request.getValueByName("map"))
  103. if os.path.isfile(request.getValueByName("map")):
  104. mapobj = mapscript.mapObj(request.getValueByName("map"))
  105. # there is 'map' parameter in URL BUT the file does not exist:
  106. # create
  107. else:
  108. mapobj = self.makeMap(request.getValueByName("map"))
  109. # WFS Filter encoding, if available
  110. if request.getValueByName("fes"):
  111. self.setFilter(mapobj,request)
  112. mapobj.OWSDispatch(request)
  113. def getMapObj(self,mapfilename=None):
  114. self.__getCacheDir()
  115. if self.url is not None and self.capabilities is None:
  116. self.__getCapabilities()
  117. mapobj = mapscript.mapObj()
  118. mapobj.setMetaData("wms_onlineresource",self.getOnlineResource(self.config.get("MapServer","onlineresource"),mapfilename))
  119. logging.debug("Setting SRS to %s"%self.config.get("MapServer","srs"))
  120. mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
  121. mapobj.setProjection("init=epsg:4326")
  122. mapobj.setSize(500,500)
  123. mapobj.setExtent(-180,-90,90,180)
  124. mapobj.shapepath = self.cachedir
  125. mapobj.setMetaData("wms_encoding","utf-8")
  126. errfile = self.config.get("MapServer","errorfile")
  127. logging.debug("Setting ERRORFILE to %s"%errfile)
  128. if not os.path.exists(errfile) and errfile != "stderr":
  129. tmp = open(errfile,"w")
  130. tmp.close()
  131. # file
  132. if os.access(errfile, os.W_OK):
  133. mapobj.setConfigOption("MS_ERRORFILE",errfile)
  134. # stderr
  135. elif errfile == "stderr":
  136. mapobj.setConfigOption("MS_ERRORFILE",errfile)
  137. # no error file set
  138. else:
  139. logging.warning("Cannot set ERRORFILE to %s: %s " % (errfile,"Write access denided"))
  140. logging.debug("Setting IMAGEPATH to %s"%self.config.get("MapServer","imagepath"))
  141. mapobj.web.imagepath=self.config.get("MapServer","imagepath")
  142. mapobj.setMetaData("ows_enable_request","*")
  143. return mapobj
  144. def saveMapfile(self,mapobj,mapfilename):
  145. self.mapfilename = self.getMapfileLocation(mapfilename)
  146. if self.mapfilename:
  147. # save mapfile ONLY if GetCapabilities requested - it makes no
  148. # sense for other cases
  149. logging.info("Saving mapfile to %s" % self.mapfilename)
  150. mapobj.save(self.mapfilename)
  151. else:
  152. logging.info("Mapfile NOT saved")
  153. return self.mapfilename
  154. def getLayerUrl(self):
  155. layerurl = self.url
  156. if self.url.find("?") > -1:
  157. if not self.url.endswith("?") and\
  158. not self.url.endswith("&"):
  159. layerurl += "&"
  160. else:
  161. layerurl += "?"
  162. return layerurl
  163. def createLayerDefinitionFile(self, name,
  164. templatefile,time=None,target=None):
  165. layerurl = self.getLayerUrl()
  166. defFileName = None
  167. if target:
  168. defFileName = target
  169. else:
  170. defFileName = os.path.join(self.cachedir,'%s.%s'%(name,self.service.lower()))
  171. if time:
  172. time = "<DefaultTime>"+time+"</DefaultTime>"
  173. else:
  174. time = ""
  175. open(defFileName,'w').write(
  176. Template(open(templatefile).read()).substitute(
  177. dict(url= layerurl, name=name,time=time)))
  178. logging.debug("Created %s layer definition file" % defFileName)
  179. return defFileName
  180. def getLayerExtent(self,layer,crs=None,wkt=None):
  181. """Get extent of layer in form of minx, miny, maxx,maxy
  182. """
  183. bbox = None
  184. if layer.boundingBoxWGS84:
  185. dest = osr.SpatialReference()
  186. if crs:
  187. dest.ImportFromEPSG(int(crs.split(":")[1]))
  188. else:
  189. dest.ImportFromWkt(wkt)
  190. source = osr.SpatialReference()
  191. source.ImportFromEPSG(4326)
  192. bbox = []
  193. # TODO rewrite this using ogr CoordinateTransformation
  194. # http://www.gdal.org/ogr/osr_tutorial.html
  195. geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[0],layer.boundingBoxWGS84[1]),source)
  196. geom.TransformTo(dest)
  197. bbox.append(geom.GetX())
  198. bbox.append(geom.GetY())
  199. geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[2],layer.boundingBoxWGS84[3]),source)
  200. geom.TransformTo(dest)
  201. bbox.append(geom.GetX())
  202. bbox.append(geom.GetY())
  203. logging.debug("Setting extent for layer <%s> to %s" %\
  204. (layer.id,bbox))
  205. return bbox
  206. def setFilter(self,mapobj,request):
  207. """ Set WFS filter encoding
  208. """
  209. logging.debug("Setting filter for layer %s to %s" % (request.getValueByName("layers"),request.getValueByName("fes")))
  210. layerobj = mapobj.getLayerByName(request.getValueByName("layers"))
  211. layerobj.setMetaData("wfs_filter",request.getValueByName("fes"))
  212. def getService():
  213. qstring = os.environ["QUERY_STRING"]
  214. params = urlparse.parse_qs(qstring)
  215. owsUrl = urllib.unquote(params["owsUrl"][0])
  216. if params["owsService"][0].lower() == "wfs":
  217. from wfs import WFS
  218. return WFS(owsUrl,qstring)
  219. elif params["owsService"][0].lower() == "wcs":
  220. from wcs import WCS
  221. return WCS(owsUrl,qstring)