def __init__(self, configpath): conf = SafeConfigParser() conf.readfp(open(configpath)) self.conf = conf if not conf.has_option_with_value('server', 'module'): raise ServerConfigurationError( 'The factory module is not defined in the configuration file.') try: mapfactorymodule = __import__(conf.get('server', 'module')) except ImportError: raise ServerConfigurationError( 'The factory module could not be loaded.') if hasattr(mapfactorymodule, 'WMSFactory'): self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')() else: raise ServerConfigurationError( 'The factory module does not have a WMSFactory class.') if conf.has_option('server', 'debug'): self.debug = int(conf.get('server', 'debug')) else: self.debug = 0 if self.conf.has_option_with_value('server', 'maxage'): self.max_age = 'max-age=%d' % self.conf.get('server', 'maxage') else: self.max_age = None
def processServiceCapabilities(self, capetree): if len(self.conf.items('service')) > 0: servicee = capetree.find('{http://www.opengis.net/wms}Service') for item in self.CONF_SERVICE: if self.conf.has_option_with_value('service', item[0]): value = self.conf.get('service', item[0]).strip() try: item[2](value) except: raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) if item[0] == 'onlineresource': element = ElementTree.Element('%s' % item[1]) servicee.append(element) element.set('{http://www.w3.org/1999/xlink}href', value) element.set('{http://www.w3.org/1999/xlink}type', 'simple') elif item[0] == 'keywordlist': element = ElementTree.Element('%s' % item[1]) servicee.append(element) keywords = value.split(',') keywords = map(str.strip, keywords) for keyword in keywords: kelement = ElementTree.Element('Keyword') kelement.text = keyword element.append(kelement) else: element = ElementTree.Element('%s' % item[1]) element.text = value servicee.append(element) if len(self.conf.items_with_value('contact')) > 0: element = ElementTree.Element('ContactInformation') servicee.append(element) for item in self.CONF_CONTACT: if self.conf.has_option_with_value('contact', item[0]): value = self.conf.get('contact', item[0]).strip() try: item[2](value) except: raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) celement = ElementTree.Element('%s' % item[1]) celement.text = value element.append(celement) for item in self.CONF_CONTACT_PERSON_PRIMARY + self.CONF_CONTACT_ADDRESS: if item in self.CONF_CONTACT_PERSON_PRIMARY: tagname = 'ContactPersonPrimary' else: tagname = 'ContactAddress' if self.conf.has_option_with_value('contact', item[0]): if element.find(tagname) == None: subelement = ElementTree.Element(tagname) element.append(subelement) value = self.conf.get('contact', item[0]).strip() try: item[2](value) except: raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) celement = ElementTree.Element('%s' % item[1]) celement.text = value subelement.append(celement)
def register_style(self, name, style): if not name: raise ServerConfigurationError( 'Attempted to register a style without providing a name.') if not isinstance(style, Style): raise ServerConfigurationError( 'Bad style object passed to register_style() for style "%s".' % name) self.styles[name] = style
def finalize(self): if len(self.layers) == 0: raise ServerConfigurationError('No layers defined!') if len(self.styles) == 0: raise ServerConfigurationError('No styles defined!') for layer in self.layers.values(): for style in list(layer.styles) + list(layer.wmsextrastyles): if style not in self.styles.keys(): raise ServerConfigurationError( 'Layer "%s" refers to undefined style "%s".' % (layer.name(), style))
def register_layer(self, layer, extrastyles=()): layername = layer.name() if not layername: raise ServerConfigurationError( 'Attempted to register an unnamed layer.') self.layers[layername] = layer if isinstance(extrastyles, tuple): layer.wmsextrastyles = extrastyles else: raise ServerConfigurationError( 'Layer "%s" was passed an invalid list of extra styles. List must be a tuple of strings.' % layername)
def register_style(self, name, style): if not name: raise ServerConfigurationError( 'Attempted to register a style without providing a name.') if name in self.aggregatestyles.keys() or name in self.styles.keys(): raise ServerConfigurationError( "Attempted to register a style with a name already in use: '%s'" % name) if not isinstance(style, Style): raise ServerConfigurationError( 'Bad style object passed to register_style() for style "%s".' % name) self.styles[name] = style
def loadXML(self, xmlfile, strict=False): tmp_map = Map(0, 0) load_map(tmp_map, xmlfile, strict) for lyr in tmp_map.layers: style_count = len(lyr.styles) if style_count == 0: raise ServerConfigurationError( "Cannot register Layer '%s' without a style" % lyr.name) elif style_count == 1: style_obj = tmp_map.find_style(lyr.styles[0]) style_obj = copy_style(style_obj) style_name = lyr.styles[0] if style_name not in self.aggregatestyles.keys( ) and style_name not in self.styles.keys(): self.register_style(style_name, style_obj) self.register_layer(copy_layer(lyr), style_name, extrastyles=(style_name, )) elif style_count > 1: for style_name in lyr.styles: style_obj = tmp_map.find_style(style_name) style_obj = copy_style(style_obj) if style_name not in self.aggregatestyles.keys( ) and style_name not in self.styles.keys(): self.register_style(style_name, style_obj) aggregates = tuple([sty for sty in lyr.styles]) aggregates_name = '%s_aggregates' % lyr.name self.register_aggregate_style(aggregates_name, aggregates) self.register_layer(copy_layer(lyr), aggregates_name, extrastyles=aggregates)
def register_aggregate_style(self, name, stylenames): if not name: raise ServerConfigurationError( 'Attempted to register an aggregate style without providing a name.' ) if name in self.aggregatestyles.keys() or name in self.styles.keys(): raise ServerConfigurationError( 'Attempted to register an aggregate style with a name already in use.' ) self.aggregatestyles[name] = [] for stylename in stylenames: if stylename not in self.styles.keys(): raise ServerConfigurationError( 'Attempted to register an aggregate style containing a style that does not exist.' ) self.aggregatestyles[name].append(stylename)
def _buildMap(self, params): if str(params['crs']) not in self.allowedepsgcodes: raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') if params['bbox'][0] >= params['bbox'][2]: raise OGCException("BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: 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']): raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height'], '+init=%s' % params['crs']) if params.has_key('transparent') and params['transparent'] == 'FALSE': if params['bgcolor']: m.background = params['bgcolor'] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers orderedmaplayers = self.mapfactory.ordered_layers mapstyles = self.mapfactory.styles mapaggregatestyles = self.mapfactory.aggregatestyles # a non WMS spec way of requesting all layers if params['layers'] and params['layers'][0] == '__all__': for layername in orderedmaplayers: layer = copy_layer(layername) reqstyle = layer.wmsdefaultstyle if reqstyle in mapaggregatestyles.keys(): for stylename in mapaggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) m.layers.append(layer) else: for layerindex, layername in enumerate(params['layers']): try: layer = copy_layer(maplayers[layername]) except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') try: reqstyle = params['styles'][layerindex] except IndexError: reqstyle = '' if reqstyle and reqstyle not in layer.wmsextrastyles: raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') if not reqstyle: reqstyle = layer.wmsdefaultstyle if reqstyle in mapaggregatestyles.keys(): for stylename in mapaggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box(Box2d(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) return m
def __init__(self, mandatory, cast, default=None, allowedvalues=None, fallback=False): """ An OGC request parameter definition. Used to describe a parameter's characteristics. @param mandatory: Is this parameter required by the request? @type mandatory: Boolean. @param default: Default value to use if one is not provided and the parameter is optional. @type default: None or any valid value. @param allowedvalues: A list of allowed values for the parameter. If a value is provided that is not in this list, an error is raised. @type allowedvalues: A python tuple of values. @param fallback: Whether the value of the parameter should fall back to the default should an illegal value be provided. @type fallback: Boolean. @return: A L{ParameterDefinition} instance. """ if mandatory not in [True, False]: raise ServerConfigurationError( "Bad value for 'mandatory' parameter, must be True or False.") self.mandatory = mandatory if not callable(cast): raise ServerConfigurationError( 'Cast parameter definition must be callable.') self.cast = cast self.default = default if allowedvalues and type(allowedvalues) != type(()): raise ServerConfigurationError( "Bad value for 'allowedvalues' parameter, must be a tuple.") self.allowedvalues = allowedvalues if fallback not in [True, False]: raise ServerConfigurationError( "Bad value for 'fallback' parameter, must be True or False.") self.fallback = fallback
def __init__(self, conf, mapfactory, opsonlineresource): self.conf = conf self.mapfactory = mapfactory self.opsonlineresource = opsonlineresource if self.conf.has_option('service', 'allowedepsgcodes'): self.allowedepsgcodes = map( lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(',')) else: raise ServerConfigurationError( 'Allowed EPSG codes not properly configured.') self.capabilities = None
def register_layer(self, layer, defaultstyle, extrastyles=()): layername = layer.name if not layername: raise ServerConfigurationError( 'Attempted to register an unnamed layer.') if not re.match('^\+init=epsg:\d+$', layer.srs) and not re.match( '^\+proj=.*$', layer.srs): raise ServerConfigurationError( 'Attempted to register a layer without an epsg projection defined.' ) if defaultstyle not in self.styles.keys() + self.aggregatestyles.keys( ): raise ServerConfigurationError( 'Attempted to register a layer with an non-existent default style.' ) layer.wmsdefaultstyle = defaultstyle if isinstance(extrastyles, tuple): for stylename in extrastyles: if type(stylename) == type(''): if stylename not in self.styles.keys( ) + self.aggregatestyles.keys(): raise ServerConfigurationError( 'Attempted to register a layer with an non-existent extra style.' ) else: ServerConfigurationError( 'Attempted to register a layer with an invalid extra style name.' ) layer.wmsextrastyles = extrastyles else: raise ServerConfigurationError( 'Layer "%s" was passed an invalid list of extra styles. List must be a tuple of strings.' % layername) self.ordered_layers.append(layer) self.layers[layername] = layer
def GetMap(self, params): if params['bbox'][0] >= params['bbox'][2]: raise OGCException( "BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: 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']): raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height']) if params.has_key('transparent') and params['transparent'] == 'FALSE': m.background = params['bgcolor'] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers mapstyles = self.mapfactory.styles for layername in params['layers']: try: layer = maplayers[layername] except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError( 'Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box( Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) im = Image(params['width'], params['height']) render(m, im) im = fromstring('RGBA', (params['width'], params['height']), rawdata(im)) fh = StringIO() im.save(fh, PIL_TYPE_MAPPING[params['format']], quality=100) fh.seek(0) return Response(params['format'], fh.read())
def __init__(self, conf, mapfactory, opsonlineresource): self.conf = conf self.mapfactory = mapfactory if self.conf.has_option('service', 'epsg'): self.crs = CRS('EPSG', self.conf.get('service', 'epsg')) else: ServerConfigurationError('EPSG code not properly configured.') capetree = ElementTree.fromstring(self.capabilitiesxmltemplate) elements = capetree.findall('Capability//OnlineResource') for element in elements: element.set('{http://www.w3.org/1999/xlink}href', opsonlineresource) if len(self.conf.items('service')) > 0: servicee = capetree.find('Service') for item in self.CONF_SERVICE: if self.conf.has_option('service', item[0]): value = self.conf.get('service', item[0]) try: item[2](value) except: raise ServerConfigurationError( 'Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value)) if item[0] == 'onlineresource': element = ElementTree.Element('%s' % item[1]) servicee.append(element) element.set('{http://www.w3.org/1999/xlink}href', value) element.set('{http://www.w3.org/1999/xlink}type', 'simple') else: element = ElementTree.Element('%s' % item[1]) element.text = value servicee.append(element) rootlayerelem = capetree.find('Capability/Layer') rootlayersrs = rootlayerelem.find('SRS') rootlayersrs.text = str(self.crs) for layer in self.mapfactory.layers.values(): layername = ElementTree.Element('Name') layername.text = layer.name() env = layer.envelope() llp = self.crs.Inverse(env.minx, env.miny) urp = self.crs.Inverse(env.maxx, env.maxy) latlonbb = ElementTree.Element('LatLonBoundingBox') latlonbb.set('minx', str(llp[0])) latlonbb.set('miny', str(llp[1])) latlonbb.set('maxx', str(urp[0])) latlonbb.set('maxy', str(urp[1])) layerbbox = ElementTree.Element('BoundingBox') layerbbox.set('SRS', str(self.crs)) layerbbox.set('minx', str(env.minx)) layerbbox.set('miny', str(env.miny)) layerbbox.set('maxx', str(env.maxx)) layerbbox.set('maxy', str(env.maxy)) layere = ElementTree.Element('Layer') layere.append(layername) if layer.title(): layertitle = ElementTree.Element('Title') layertitle.text = layer.title() layere.append(layertitle) if layer.abstract(): layerabstract = ElementTree.Element('Abstract') layerabstract.text = layer.abstract() layere.append(layerabstract) layere.append(latlonbb) layere.append(layerbbox) if len(layer.wmsextrastyles) > 0: for extrastyle in list(layer.wmsextrastyles): style = ElementTree.Element('Style') stylename = ElementTree.Element('Name') stylename.text = extrastyle styletitle = ElementTree.Element('Title') styletitle.text = extrastyle style.append(stylename) style.append(styletitle) layere.append(style) rootlayerelem.append(layere) self.capabilities = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n' + ElementTree.tostring( capetree)
def __init__(self, conf, mapfactory, opsonlineresource): self.conf = conf self.mapfactory = mapfactory if self.conf.has_option('service', 'allowedepsgcodes'): self.allowedepsgcodes = map( lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(',')) else: raise ServerConfigurationError( 'Allowed EPSG codes not properly configured.') capetree = ElementTree.fromstring(self.capabilitiesxmltemplate) elements = capetree.findall('Capability//OnlineResource') for element in elements: element.set('{http://www.w3.org/1999/xlink}href', opsonlineresource) self.processServiceCapabilities(capetree) rootlayerelem = capetree.find( '{http://www.opengis.net/wms}Capability/{http://www.opengis.net/wms}Layer' ) for epsgcode in self.allowedepsgcodes: rootlayercrs = ElementTree.Element('SRS') rootlayercrs.text = epsgcode.upper() rootlayerelem.append(rootlayercrs) for layer in self.mapfactory.layers.values(): layerproj = Projection(layer.srs) layername = ElementTree.Element('Name') layername.text = layer.name env = layer.envelope() llp = layerproj.inverse(Coord(env.minx, env.miny)) urp = layerproj.inverse(Coord(env.maxx, env.maxy)) latlonbb = ElementTree.Element('LatLonBoundingBox') latlonbb.set('minx', str(llp.x)) latlonbb.set('miny', str(llp.y)) latlonbb.set('maxx', str(urp.x)) latlonbb.set('maxy', str(urp.y)) layerbbox = ElementTree.Element('BoundingBox') layerbbox.set('SRS', layerproj.epsgstring()) layerbbox.set('minx', str(env.minx)) layerbbox.set('miny', str(env.miny)) layerbbox.set('maxx', str(env.maxx)) layerbbox.set('maxy', str(env.maxy)) layere = ElementTree.Element('Layer') layere.append(layername) if layer.title: layertitle = ElementTree.Element('Title') layertitle.text = layer.title layere.append(layertitle) if layer.abstract: layerabstract = ElementTree.Element('Abstract') layerabstract.text = layer.abstract layere.append(layerabstract) if layer.queryable: layere.set('queryable', '1') layere.append(latlonbb) layere.append(layerbbox) if len(layer.wmsextrastyles) > 0: for extrastyle in [layer.wmsdefaultstyle] + list( layer.wmsextrastyles): style = ElementTree.Element('Style') stylename = ElementTree.Element('Name') stylename.text = extrastyle styletitle = ElementTree.Element('Title') styletitle.text = extrastyle style.append(stylename) style.append(styletitle) layere.append(style) rootlayerelem.append(layere) self.capabilities = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n' + ElementTree.tostring( capetree)