convert to unix line endings

This commit is contained in:
Dane Springmeyer 2009-02-12 01:17:30 +00:00
parent 75d5e1c9e1
commit da9640c39d
3 changed files with 580 additions and 580 deletions

View file

@ -1,459 +1,459 @@
# #
# This file is part of Mapnik (c++ mapping toolkit) # This file is part of Mapnik (c++ mapping toolkit)
# #
# Copyright (C) 2006 Jean-Francois Doyon # Copyright (C) 2006 Jean-Francois Doyon
# #
# Mapnik is free software; you can redistribute it and/or # Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either # License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version. # version 2.1 of the License, or (at your option) any later version.
# #
# This library is distributed in the hope that it will be useful, # This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details. # Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #
# $Id$ # $Id$
from exceptions import OGCException, ServerConfigurationError from exceptions import OGCException, ServerConfigurationError
from mapnik import Map, Color, Envelope, render, Image, Projection as MapnikProjection, render_to_file, Coord from mapnik import Map, Color, Envelope, render, Image, Projection as MapnikProjection, render_to_file, Coord
from PIL.Image import fromstring, new from PIL.Image import fromstring, new
from PIL.ImageDraw import Draw from PIL.ImageDraw import Draw
from StringIO import StringIO from StringIO import StringIO
from copy import deepcopy from copy import deepcopy
from traceback import format_exception, format_exception_only from traceback import format_exception, format_exception_only
from sys import exc_info from sys import exc_info
from lxml import etree as ElementTree from lxml import etree as ElementTree
import re import re
import sys import sys
# from elementtree import ElementTree # from elementtree import ElementTree
# ElementTree._namespace_map.update({'http://www.opengis.net/wms': 'wms', # ElementTree._namespace_map.update({'http://www.opengis.net/wms': 'wms',
# 'http://www.opengis.net/ogc': 'ogc', # 'http://www.opengis.net/ogc': 'ogc',
# 'http://www.w3.org/1999/xlink': 'xlink', # 'http://www.w3.org/1999/xlink': 'xlink',
# 'http://www.w3.org/2001/XMLSchema-instance': 'xsi' # 'http://www.w3.org/2001/XMLSchema-instance': 'xsi'
# }) # })
PIL_TYPE_MAPPING = {'image/jpeg': 'jpeg', 'image/png': 'png'} PIL_TYPE_MAPPING = {'image/jpeg': 'jpeg', 'image/png': 'png'}
class ParameterDefinition: class ParameterDefinition:
def __init__(self, mandatory, cast, default=None, allowedvalues=None, fallback=False): def __init__(self, mandatory, cast, default=None, allowedvalues=None, fallback=False):
""" An OGC request parameter definition. Used to describe a """ An OGC request parameter definition. Used to describe a
parameter's characteristics. parameter's characteristics.
@param mandatory: Is this parameter required by the request? @param mandatory: Is this parameter required by the request?
@type mandatory: Boolean. @type mandatory: Boolean.
@param default: Default value to use if one is not provided @param default: Default value to use if one is not provided
and the parameter is optional. and the parameter is optional.
@type default: None or any valid value. @type default: None or any valid value.
@param allowedvalues: A list of allowed values for the parameter. @param allowedvalues: A list of allowed values for the parameter.
If a value is provided that is not in this If a value is provided that is not in this
list, an error is raised. list, an error is raised.
@type allowedvalues: A python tuple of values. @type allowedvalues: A python tuple of values.
@param fallback: Whether the value of the parameter should fall @param fallback: Whether the value of the parameter should fall
back to the default should an illegal value be back to the default should an illegal value be
provided. provided.
@type fallback: Boolean. @type fallback: Boolean.
@return: A L{ParameterDefinition} instance. @return: A L{ParameterDefinition} instance.
""" """
if mandatory not in [True, False]: if mandatory not in [True, False]:
raise ServerConfigurationError("Bad value for 'mandatory' parameter, must be True or False.") raise ServerConfigurationError("Bad value for 'mandatory' parameter, must be True or False.")
self.mandatory = mandatory self.mandatory = mandatory
if not callable(cast): if not callable(cast):
raise ServerConfigurationError('Cast parameter definition must be callable.') raise ServerConfigurationError('Cast parameter definition must be callable.')
self.cast = cast self.cast = cast
self.default = default self.default = default
if allowedvalues and type(allowedvalues) != type(()): if allowedvalues and type(allowedvalues) != type(()):
raise ServerConfigurationError("Bad value for 'allowedvalues' parameter, must be a tuple.") raise ServerConfigurationError("Bad value for 'allowedvalues' parameter, must be a tuple.")
self.allowedvalues = allowedvalues self.allowedvalues = allowedvalues
if fallback not in [True, False]: if fallback not in [True, False]:
raise ServerConfigurationError("Bad value for 'fallback' parameter, must be True or False.") raise ServerConfigurationError("Bad value for 'fallback' parameter, must be True or False.")
self.fallback = fallback self.fallback = fallback
class BaseServiceHandler: class BaseServiceHandler:
CONF_CONTACT_PERSON_PRIMARY = [ CONF_CONTACT_PERSON_PRIMARY = [
['contactperson', 'ContactPerson', str], ['contactperson', 'ContactPerson', str],
['contactorganization', 'ContactOrganization', str] ['contactorganization', 'ContactOrganization', str]
] ]
CONF_CONTACT_ADDRESS = [ CONF_CONTACT_ADDRESS = [
['addresstype', 'AddressType', str], ['addresstype', 'AddressType', str],
['address', 'Address', str], ['address', 'Address', str],
['city', 'City', str], ['city', 'City', str],
['stateorprovince', 'StateOrProvince', str], ['stateorprovince', 'StateOrProvince', str],
['postcode', 'PostCode', str], ['postcode', 'PostCode', str],
['country', 'Country', str] ['country', 'Country', str]
] ]
CONF_CONTACT = [ CONF_CONTACT = [
['contactposition', 'ContactPosition', str], ['contactposition', 'ContactPosition', str],
['contactvoicetelephone', 'ContactVoiceTelephone', str], ['contactvoicetelephone', 'ContactVoiceTelephone', str],
['contactelectronicmailaddress', 'ContactElectronicMailAddress', str] ['contactelectronicmailaddress', 'ContactElectronicMailAddress', str]
] ]
def processParameters(self, requestname, params): def processParameters(self, requestname, params):
finalparams = {} finalparams = {}
for paramname, paramdef in self.SERVICE_PARAMS[requestname].items(): for paramname, paramdef in self.SERVICE_PARAMS[requestname].items():
if paramname not in params.keys() and paramdef.mandatory: if paramname not in params.keys() and paramdef.mandatory:
raise OGCException('Mandatory parameter "%s" missing from request.' % paramname) raise OGCException('Mandatory parameter "%s" missing from request.' % paramname)
elif paramname in params.keys(): elif paramname in params.keys():
try: try:
params[paramname] = paramdef.cast(params[paramname]) params[paramname] = paramdef.cast(params[paramname])
except OGCException: except OGCException:
raise raise
except: except:
raise OGCException('Invalid value "%s" for parameter "%s".' % (params[paramname], paramname)) raise OGCException('Invalid value "%s" for parameter "%s".' % (params[paramname], paramname))
if paramdef.allowedvalues and params[paramname] not in paramdef.allowedvalues: if paramdef.allowedvalues and params[paramname] not in paramdef.allowedvalues:
if not paramdef.fallback: if not paramdef.fallback:
raise OGCException('Parameter "%s" has an illegal value.' % paramname) raise OGCException('Parameter "%s" has an illegal value.' % paramname)
else: else:
finalparams[paramname] = paramdef.default finalparams[paramname] = paramdef.default
else: else:
finalparams[paramname] = params[paramname] finalparams[paramname] = params[paramname]
elif not paramdef.mandatory and paramdef.default: elif not paramdef.mandatory and paramdef.default:
finalparams[paramname] = paramdef.default finalparams[paramname] = paramdef.default
return finalparams return finalparams
def processServiceCapabilities(self, capetree): def processServiceCapabilities(self, capetree):
if len(self.conf.items('service')) > 0: if len(self.conf.items('service')) > 0:
servicee = capetree.find('{http://www.opengis.net/wms}Service') servicee = capetree.find('{http://www.opengis.net/wms}Service')
for item in self.CONF_SERVICE: for item in self.CONF_SERVICE:
if self.conf.has_option_with_value('service', item[0]): if self.conf.has_option_with_value('service', item[0]):
value = self.conf.get('service', item[0]).strip() value = self.conf.get('service', item[0]).strip()
try: try:
item[2](value) item[2](value)
except: except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
if item[0] == 'onlineresource': if item[0] == 'onlineresource':
element = ElementTree.Element('%s' % item[1]) element = ElementTree.Element('%s' % item[1])
servicee.append(element) servicee.append(element)
element.set('{http://www.w3.org/1999/xlink}href', value) element.set('{http://www.w3.org/1999/xlink}href', value)
element.set('{http://www.w3.org/1999/xlink}type', 'simple') element.set('{http://www.w3.org/1999/xlink}type', 'simple')
elif item[0] == 'keywordlist': elif item[0] == 'keywordlist':
element = ElementTree.Element('%s' % item[1]) element = ElementTree.Element('%s' % item[1])
servicee.append(element) servicee.append(element)
keywords = value.split(',') keywords = value.split(',')
keywords = map(str.strip, keywords) keywords = map(str.strip, keywords)
for keyword in keywords: for keyword in keywords:
kelement = ElementTree.Element('Keyword') kelement = ElementTree.Element('Keyword')
kelement.text = keyword kelement.text = keyword
element.append(kelement) element.append(kelement)
else: else:
element = ElementTree.Element('%s' % item[1]) element = ElementTree.Element('%s' % item[1])
element.text = value element.text = value
servicee.append(element) servicee.append(element)
if len(self.conf.items_with_value('contact')) > 0: if len(self.conf.items_with_value('contact')) > 0:
element = ElementTree.Element('ContactInformation') element = ElementTree.Element('ContactInformation')
servicee.append(element) servicee.append(element)
for item in self.CONF_CONTACT: for item in self.CONF_CONTACT:
if self.conf.has_option_with_value('contact', item[0]): if self.conf.has_option_with_value('contact', item[0]):
value = self.conf.get('contact', item[0]).strip() value = self.conf.get('contact', item[0]).strip()
try: try:
item[2](value) item[2](value)
except: except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
celement = ElementTree.Element('%s' % item[1]) celement = ElementTree.Element('%s' % item[1])
celement.text = value celement.text = value
element.append(celement) element.append(celement)
for item in self.CONF_CONTACT_PERSON_PRIMARY + self.CONF_CONTACT_ADDRESS: for item in self.CONF_CONTACT_PERSON_PRIMARY + self.CONF_CONTACT_ADDRESS:
if item in self.CONF_CONTACT_PERSON_PRIMARY: if item in self.CONF_CONTACT_PERSON_PRIMARY:
tagname = 'ContactPersonPrimary' tagname = 'ContactPersonPrimary'
else: else:
tagname = 'ContactAddress' tagname = 'ContactAddress'
if self.conf.has_option_with_value('contact', item[0]): if self.conf.has_option_with_value('contact', item[0]):
if element.find(tagname) == None: if element.find(tagname) == None:
subelement = ElementTree.Element(tagname) subelement = ElementTree.Element(tagname)
element.append(subelement) element.append(subelement)
value = self.conf.get('contact', item[0]).strip() value = self.conf.get('contact', item[0]).strip()
try: try:
item[2](value) item[2](value)
except: except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
celement = ElementTree.Element('%s' % item[1]) celement = ElementTree.Element('%s' % item[1])
celement.text = value celement.text = value
subelement.append(celement) subelement.append(celement)
class Response: class Response:
def __init__(self, content_type, content): def __init__(self, content_type, content):
self.content_type = content_type self.content_type = content_type
self.content = content self.content = content
class Version: class Version:
def __init__(self, version): def __init__(self, version):
version = version.split('.') version = version.split('.')
if len(version) != 3: if len(version) != 3:
raise OGCException('Badly formatted version number.') raise OGCException('Badly formatted version number.')
try: try:
version = map(int, version) version = map(int, version)
except: except:
raise OGCException('Badly formatted version number.') raise OGCException('Badly formatted version number.')
self.version = version self.version = version
def __repr__(self): def __repr__(self):
return '%s.%s.%s' % (self.version[0], self.version[1], self.version[2]) return '%s.%s.%s' % (self.version[0], self.version[1], self.version[2])
def __cmp__(self, other): def __cmp__(self, other):
if isinstance(other, str): if isinstance(other, str):
other = Version(other) other = Version(other)
if self.version[0] < other.version[0]: if self.version[0] < other.version[0]:
return -1 return -1
elif self.version[0] > other.version[0]: elif self.version[0] > other.version[0]:
return 1 return 1
else: else:
if self.version[1] < other.version[1]: if self.version[1] < other.version[1]:
return -1 return -1
elif self.version[1] > other.version[1]: elif self.version[1] > other.version[1]:
return 1 return 1
else: else:
if self.version[2] < other.version[2]: if self.version[2] < other.version[2]:
return -1 return -1
elif self.version[2] > other.version[2]: elif self.version[2] > other.version[2]:
return 1 return 1
else: else:
return 0 return 0
class ListFactory: class ListFactory:
def __init__(self, cast): def __init__(self, cast):
self.cast = cast self.cast = cast
def __call__(self, string): def __call__(self, string):
seq = string.split(',') seq = string.split(',')
return map(self.cast, seq) return map(self.cast, seq)
def ColorFactory(colorstring): def ColorFactory(colorstring):
if re.match('^0x[a-fA-F0-9]{6}$', colorstring): if re.match('^0x[a-fA-F0-9]{6}$', colorstring):
return Color(eval('0x' + colorstring[2:4]), eval('0x' + colorstring[4:6]), eval('0x' + colorstring[6:8])) return Color(eval('0x' + colorstring[2:4]), eval('0x' + colorstring[4:6]), eval('0x' + colorstring[6:8]))
else: else:
raise OGCException('Invalid color value. Must be of format "0xFFFFFF".') raise OGCException('Invalid color value. Must be of format "0xFFFFFF".')
class CRS: class CRS:
def __init__(self, namespace, code): def __init__(self, namespace, code):
self.namespace = namespace.lower() self.namespace = namespace.lower()
self.code = int(code) self.code = int(code)
self.proj = None self.proj = None
def __repr__(self): def __repr__(self):
return '%s:%s' % (self.namespace, self.code) return '%s:%s' % (self.namespace, self.code)
def __eq__(self, other): def __eq__(self, other):
if str(other) == str(self): if str(other) == str(self):
return True return True
return False return False
def inverse(self, x, y): def inverse(self, x, y):
if not self.proj: if not self.proj:
self.proj = Projection('+init=%s:%s' % (self.namespace, self.code)) self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
return self.proj.inverse(Coord(x, y)) return self.proj.inverse(Coord(x, y))
def forward(self, x, y): def forward(self, x, y):
if not self.proj: if not self.proj:
self.proj = Projection('+init=%s:%s' % (self.namespace, self.code)) self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
return self.proj.forward(Coord(x, y)) return self.proj.forward(Coord(x, y))
class CRSFactory: class CRSFactory:
def __init__(self, allowednamespaces): def __init__(self, allowednamespaces):
self.allowednamespaces = allowednamespaces self.allowednamespaces = allowednamespaces
def __call__(self, crsstring): def __call__(self, crsstring):
if not re.match('^[A-Z]{3,5}:\d+$', crsstring): if not re.match('^[A-Z]{3,5}:\d+$', crsstring):
raise OGCException('Invalid format for the CRS parameter: %s' % crsstring, 'InvalidCRS') raise OGCException('Invalid format for the CRS parameter: %s' % crsstring, 'InvalidCRS')
crsparts = crsstring.split(':') crsparts = crsstring.split(':')
if crsparts[0] in self.allowednamespaces: if crsparts[0] in self.allowednamespaces:
return CRS(crsparts[0], crsparts[1]) return CRS(crsparts[0], crsparts[1])
else: else:
raise OGCException('Invalid CRS Namespace: %s' % crsparts[0], 'InvalidCRS') raise OGCException('Invalid CRS Namespace: %s' % crsparts[0], 'InvalidCRS')
class WMSBaseServiceHandler(BaseServiceHandler): class WMSBaseServiceHandler(BaseServiceHandler):
def GetMap(self, params): def GetMap(self, params):
m = self._buildMap(params) m = self._buildMap(params)
im = Image(params['width'], params['height']) im = Image(params['width'], params['height'])
render(m, im) render(m, im)
return Response(params['format'], im.tostring(PIL_TYPE_MAPPING[params['format']])) return Response(params['format'], im.tostring(PIL_TYPE_MAPPING[params['format']]))
def GetFeatureInfo(self, params, querymethodname='query_point'): def GetFeatureInfo(self, params, querymethodname='query_point'):
m = self._buildMap(params) m = self._buildMap(params)
if params['info_format'] == 'text/plain': if params['info_format'] == 'text/plain':
writer = TextFeatureInfo() writer = TextFeatureInfo()
elif params['info_format'] == 'text/xml': elif params['info_format'] == 'text/xml':
writer = XMLFeatureInfo() writer = XMLFeatureInfo()
for layerindex, layername in enumerate(params['query_layers']): for layerindex, layername in enumerate(params['query_layers']):
if layername in params['layers']: if layername in params['layers']:
if m.layers[layerindex].queryable: if m.layers[layerindex].queryable:
features = getattr(m, querymethodname)(layerindex, params['i'], params['j']) features = getattr(m, querymethodname)(layerindex, params['i'], params['j'])
if features: if features:
writer.addlayer(m.layers[layerindex].name) writer.addlayer(m.layers[layerindex].name)
for feature in features: for feature in features:
writer.addfeature() writer.addfeature()
for prop in feature.properties: for prop in feature.properties:
writer.addattribute(prop.key(), prop.data()) writer.addattribute(prop.key(), prop.data())
else: else:
raise OGCException('Requested query layer "%s" is not marked queryable.' % layername, 'LayerNotQueryable') raise OGCException('Requested query layer "%s" is not marked queryable.' % layername, 'LayerNotQueryable')
else: else:
raise OGCException('Requested query layer "%s" not in the LAYERS parameter.' % layername) raise OGCException('Requested query layer "%s" not in the LAYERS parameter.' % layername)
return Response(params['info_format'], str(writer)) return Response(params['info_format'], str(writer))
def _buildMap(self, params): def _buildMap(self, params):
if str(params['crs']) not in self.allowedepsgcodes: if str(params['crs']) not in self.allowedepsgcodes:
raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS')
if params['bbox'][0] >= params['bbox'][2]: if params['bbox'][0] >= params['bbox'][2]:
raise OGCException("BBOX values don't make sense. minx is greater than maxx.") raise OGCException("BBOX values don't make sense. minx is greater than maxx.")
if params['bbox'][1] >= params['bbox'][3]: if params['bbox'][1] >= params['bbox'][3]:
raise OGCException("BBOX values don't make sense. miny is greater than maxy.") raise OGCException("BBOX values don't make sense. miny is greater than maxy.")
if params.has_key('styles') and len(params['styles']) != len(params['layers']): if params.has_key('styles') and len(params['styles']) != len(params['layers']):
raise OGCException('STYLES length does not match LAYERS length.') raise OGCException('STYLES length does not match LAYERS length.')
m = Map(params['width'], params['height'], '+init=%s' % params['crs']) m = Map(params['width'], params['height'], '+init=%s' % params['crs'])
if params.has_key('transparent') and params['transparent'] == 'FALSE': if params.has_key('transparent') and params['transparent'] == 'FALSE':
m.background = params['bgcolor'] m.background = params['bgcolor']
else: else:
m.background = Color(0, 0, 0, 0) m.background = Color(0, 0, 0, 0)
maplayers = self.mapfactory.layers maplayers = self.mapfactory.layers
mapstyles = self.mapfactory.styles mapstyles = self.mapfactory.styles
mapaggregatestyles = self.mapfactory.aggregatestyles mapaggregatestyles = self.mapfactory.aggregatestyles
for layerindex, layername in enumerate(params['layers']): for layerindex, layername in enumerate(params['layers']):
try: try:
layer = maplayers[layername] layer = maplayers[layername]
except KeyError: except KeyError:
raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined')
reqstyle = params['styles'][layerindex] reqstyle = params['styles'][layerindex]
if reqstyle and reqstyle not in layer.wmsextrastyles: if reqstyle and reqstyle not in layer.wmsextrastyles:
raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined')
if not reqstyle: if not reqstyle:
reqstyle = layer.wmsdefaultstyle reqstyle = layer.wmsdefaultstyle
if reqstyle in mapaggregatestyles.keys(): if reqstyle in mapaggregatestyles.keys():
for stylename in mapaggregatestyles[reqstyle]: for stylename in mapaggregatestyles[reqstyle]:
layer.styles.append(stylename) layer.styles.append(stylename)
else: else:
layer.styles.append(reqstyle) layer.styles.append(reqstyle)
for stylename in layer.styles: for stylename in layer.styles:
if stylename in mapstyles.keys(): if stylename in mapstyles.keys():
m.append_style(stylename, mapstyles[stylename]) m.append_style(stylename, mapstyles[stylename])
else: else:
raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename))
m.layers.append(layer) m.layers.append(layer)
m.zoom_to_box(Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) m.zoom_to_box(Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3]))
return m return m
class BaseExceptionHandler: class BaseExceptionHandler:
def __init__(self, debug): def __init__(self, debug):
self.debug = debug self.debug = debug
def getresponse(self, params): def getresponse(self, params):
code = '' code = ''
message = '\n' message = '\n'
excinfo = exc_info() excinfo = exc_info()
if self.debug: if self.debug:
messagelist = format_exception(excinfo[0], excinfo[1], excinfo[2]) messagelist = format_exception(excinfo[0], excinfo[1], excinfo[2])
else: else:
messagelist = format_exception_only(excinfo[0], excinfo[1]) messagelist = format_exception_only(excinfo[0], excinfo[1])
message += ''.join(messagelist) message += ''.join(messagelist)
if isinstance(excinfo[1], OGCException) and len(excinfo[1].args) > 1: if isinstance(excinfo[1], OGCException) and len(excinfo[1].args) > 1:
code = excinfo[1].args[1] code = excinfo[1].args[1]
exceptions = params.get('exceptions', None) exceptions = params.get('exceptions', None)
if not exceptions or not self.handlers.has_key(exceptions): if not exceptions or not self.handlers.has_key(exceptions):
exceptions = self.defaulthandler exceptions = self.defaulthandler
return self.handlers[exceptions](self, code, message, params) return self.handlers[exceptions](self, code, message, params)
def xmlhandler(self, code, message, params): def xmlhandler(self, code, message, params):
ogcexcetree = deepcopy(self.xmltemplate) ogcexcetree = deepcopy(self.xmltemplate)
e = ogcexcetree.find(self.xpath) e = ogcexcetree.find(self.xpath)
e.text = message e.text = message
if code: if code:
e.set('code', code) e.set('code', code)
return Response(self.xmlmimetype, ElementTree.tostring(ogcexcetree)) return Response(self.xmlmimetype, ElementTree.tostring(ogcexcetree))
def inimagehandler(self, code, message, params): def inimagehandler(self, code, message, params):
im = new('RGBA', (int(params['width']), int(params['height']))) im = new('RGBA', (int(params['width']), int(params['height'])))
im.putalpha(new('1', (int(params['width']), int(params['height'])))) im.putalpha(new('1', (int(params['width']), int(params['height']))))
draw = Draw(im) draw = Draw(im)
for count, line in enumerate(message.strip().split('\n')): for count, line in enumerate(message.strip().split('\n')):
draw.text((12,15*(count+1)), line, fill='#000000') draw.text((12,15*(count+1)), line, fill='#000000')
fh = StringIO() fh = StringIO()
im.save(fh, PIL_TYPE_MAPPING[params['format']]) im.save(fh, PIL_TYPE_MAPPING[params['format']])
fh.seek(0) fh.seek(0)
return Response(params['format'], fh.read()) return Response(params['format'], fh.read())
def blankhandler(self, code, message, params): def blankhandler(self, code, message, params):
bgcolor = params.get('bgcolor', '#FFFFFF') bgcolor = params.get('bgcolor', '#FFFFFF')
bgcolor = bgcolor.replace('0x', '#') bgcolor = bgcolor.replace('0x', '#')
transparent = params.get('transparent', 'FALSE') transparent = params.get('transparent', 'FALSE')
if transparent == 'TRUE': if transparent == 'TRUE':
im = new('RGBA', (int(params['width']), int(params['height']))) im = new('RGBA', (int(params['width']), int(params['height'])))
im.putalpha(new('1', (int(params['width']), int(params['height'])))) im.putalpha(new('1', (int(params['width']), int(params['height']))))
else: else:
im = new('RGBA', (int(params['width']), int(params['height'])), bgcolor) im = new('RGBA', (int(params['width']), int(params['height'])), bgcolor)
fh = StringIO() fh = StringIO()
im.save(fh, PIL_TYPE_MAPPING[params['format']]) im.save(fh, PIL_TYPE_MAPPING[params['format']])
fh.seek(0) fh.seek(0)
return Response(params['format'], fh.read()) return Response(params['format'], fh.read())
class Projection(MapnikProjection): class Projection(MapnikProjection):
def epsgstring(self): def epsgstring(self):
return self.params().split('=')[1].upper() return self.params().split('=')[1].upper()
class TextFeatureInfo: class TextFeatureInfo:
def __init__(self): def __init__(self):
self.buffer = '' self.buffer = ''
def addlayer(self, name): def addlayer(self, name):
self.buffer += '[%s]\n' % name self.buffer += '[%s]\n' % name
def addfeature(self): def addfeature(self):
self.buffer += '\n' self.buffer += '\n'
def addattribute(self, name, value): def addattribute(self, name, value):
self.buffer += '%s=%s\n' % (name, str(value)) self.buffer += '%s=%s\n' % (name, str(value))
def __str__(self): def __str__(self):
return self.buffer return self.buffer
class XMLFeatureInfo: class XMLFeatureInfo:
basexml = """<?xml version="1.0"?> basexml = """<?xml version="1.0"?>
<resultset> <resultset>
</resultset> </resultset>
""" """
def __init__(self): def __init__(self):
self.rootelement = ElementTree.fromstring(self.basexml) self.rootelement = ElementTree.fromstring(self.basexml)
def addlayer(self, name): def addlayer(self, name):
layer = ElementTree.Element('layer') layer = ElementTree.Element('layer')
layer.set('name', name) layer.set('name', name)
self.rootelement.append(layer) self.rootelement.append(layer)
self.currentlayer = layer self.currentlayer = layer
def addfeature(self): def addfeature(self):
feature = ElementTree.Element('feature') feature = ElementTree.Element('feature')
self.currentlayer.append(feature) self.currentlayer.append(feature)
self.currentfeature = feature self.currentfeature = feature
def addattribute(self, name, value): def addattribute(self, name, value):
attribute = ElementTree.Element('attribute') attribute = ElementTree.Element('attribute')
attname = ElementTree.Element('name') attname = ElementTree.Element('name')
attname.text = name attname.text = name
attvalue = ElementTree.Element('value') attvalue = ElementTree.Element('value')
attvalue.text = value.unicode() attvalue.text = value.unicode()
attribute.append(attname) attribute.append(attname)
attribute.append(attvalue) attribute.append(attvalue)
self.currentfeature.append(attribute) self.currentfeature.append(attribute)
def __str__(self): def __str__(self):
return '<?xml version="1.0"?>\n' + ElementTree.tostring(self.rootelement) return '<?xml version="1.0"?>\n' + ElementTree.tostring(self.rootelement)

View file

@ -1,26 +1,26 @@
# #
# This file is part of Mapnik (c++ mapping toolkit) # This file is part of Mapnik (c++ mapping toolkit)
# #
# Copyright (C) 2006 Jean-Francois Doyon # Copyright (C) 2006 Jean-Francois Doyon
# #
# Mapnik is free software; you can redistribute it and/or # Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either # License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version. # version 2.1 of the License, or (at your option) any later version.
# #
# This library is distributed in the hope that it will be useful, # This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details. # Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #
# $Id$ # $Id$
class OGCException(Exception): class OGCException(Exception):
pass pass
class ServerConfigurationError(Exception): class ServerConfigurationError(Exception):
pass pass

View file

@ -1,97 +1,97 @@
# #
# This file is part of Mapnik (c++ mapping toolkit) # This file is part of Mapnik (c++ mapping toolkit)
# #
# Copyright (C) 2006 Jean-Francois Doyon # Copyright (C) 2006 Jean-Francois Doyon
# #
# Mapnik is free software; you can redistribute it and/or # Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either # License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version. # version 2.1 of the License, or (at your option) any later version.
# #
# This library is distributed in the hope that it will be useful, # This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details. # Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #
# $Id$ # $Id$
from exceptions import OGCException, ServerConfigurationError from exceptions import OGCException, ServerConfigurationError
from configparser import SafeConfigParser from configparser import SafeConfigParser
from cgi import parse_qs from cgi import parse_qs
from wms111 import ExceptionHandler as ExceptionHandler111 from wms111 import ExceptionHandler as ExceptionHandler111
from wms130 import ExceptionHandler as ExceptionHandler130 from wms130 import ExceptionHandler as ExceptionHandler130
from common import Version from common import Version
class WSGIApp: class WSGIApp:
def __init__(self, configpath): def __init__(self, configpath):
conf = SafeConfigParser() conf = SafeConfigParser()
conf.readfp(open(configpath)) conf.readfp(open(configpath))
self.conf = conf self.conf = conf
if not conf.has_option_with_value('server', 'module'): if not conf.has_option_with_value('server', 'module'):
raise ServerConfigurationError('The factory module is not defined in the configuration file.') raise ServerConfigurationError('The factory module is not defined in the configuration file.')
try: try:
mapfactorymodule = __import__(conf.get('server', 'module')) mapfactorymodule = __import__(conf.get('server', 'module'))
except ImportError: except ImportError:
raise ServerConfigurationError('The factory module could not be loaded.') raise ServerConfigurationError('The factory module could not be loaded.')
if hasattr(mapfactorymodule, 'WMSFactory'): if hasattr(mapfactorymodule, 'WMSFactory'):
self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')() self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
else: else:
raise ServerConfigurationError('The factory module does not have a WMSFactory class.') raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
if conf.has_option('server', 'debug'): if conf.has_option('server', 'debug'):
self.debug = int(conf.get('server', 'debug')) self.debug = int(conf.get('server', 'debug'))
else: else:
self.debug = 0 self.debug = 0
def __call__(self, environ, start_response): def __call__(self, environ, start_response):
reqparams = {} reqparams = {}
for key, value in parse_qs(environ['QUERY_STRING'], True).items(): for key, value in parse_qs(environ['QUERY_STRING'], True).items():
reqparams[key.lower()] = value[0] reqparams[key.lower()] = value[0]
onlineresource = 'http://%s:%s%s?' % (environ['SERVER_NAME'], environ['SERVER_PORT'], environ['SCRIPT_NAME']) onlineresource = 'http://%s:%s%s?' % (environ['SERVER_NAME'], environ['SERVER_PORT'], environ['SCRIPT_NAME'])
try: try:
if not reqparams.has_key('request'): if not reqparams.has_key('request'):
raise OGCException('Missing request parameter.') raise OGCException('Missing request parameter.')
request = reqparams['request'] request = reqparams['request']
del reqparams['request'] del reqparams['request']
if request == 'GetCapabilities' and not reqparams.has_key('service'): if request == 'GetCapabilities' and not reqparams.has_key('service'):
raise OGCException('Missing service parameter.') raise OGCException('Missing service parameter.')
if request in ['GetMap', 'GetFeatureInfo']: if request in ['GetMap', 'GetFeatureInfo']:
service = 'WMS' service = 'WMS'
else: else:
service = reqparams['service'] service = reqparams['service']
if reqparams.has_key('service'): if reqparams.has_key('service'):
del reqparams['service'] del reqparams['service']
try: try:
mapnikmodule = __import__('mapnik.ogcserver.' + service) mapnikmodule = __import__('mapnik.ogcserver.' + service)
except: except:
raise OGCException('Unsupported service "%s".' % service) raise OGCException('Unsupported service "%s".' % service)
ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None)) servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
if reqparams.has_key('version'): if reqparams.has_key('version'):
del reqparams['version'] del reqparams['version']
if request not in servicehandler.SERVICE_PARAMS.keys(): if request not in servicehandler.SERVICE_PARAMS.keys():
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported') raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
ogcparams = servicehandler.processParameters(request, reqparams) ogcparams = servicehandler.processParameters(request, reqparams)
try: try:
requesthandler = getattr(servicehandler, request) requesthandler = getattr(servicehandler, request)
except: except:
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported') raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
response = requesthandler(ogcparams) response = requesthandler(ogcparams)
except: except:
version = reqparams.get('version', None) version = reqparams.get('version', None)
if not version: if not version:
version = Version('1.3.0') version = Version('1.3.0')
else: else:
version = Version(version) version = Version(version)
if version >= '1.3.0': if version >= '1.3.0':
eh = ExceptionHandler130(self.debug) eh = ExceptionHandler130(self.debug)
else: else:
eh = ExceptionHandler111(self.debug) eh = ExceptionHandler111(self.debug)
response = eh.getresponse(reqparams) response = eh.getresponse(reqparams)
start_response('200 OK', [('Content-Type', response.content_type)]) start_response('200 OK', [('Content-Type', response.content_type)])
yield response.content yield response.content