001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wmps/configuration/WMPSConfigurationDocument.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.ogcwebservices.wmps.configuration; 037 038 import java.awt.Color; 039 import java.io.IOException; 040 import java.net.MalformedURLException; 041 import java.net.URI; 042 import java.net.URL; 043 import java.util.ArrayList; 044 import java.util.HashMap; 045 import java.util.List; 046 import java.util.Map; 047 048 import javax.xml.transform.TransformerException; 049 050 import org.deegree.datatypes.QualifiedName; 051 import org.deegree.enterprise.Proxy; 052 import org.deegree.framework.log.ILogger; 053 import org.deegree.framework.log.LoggerFactory; 054 import org.deegree.framework.util.BootLogger; 055 import org.deegree.framework.util.IDGenerator; 056 import org.deegree.framework.util.KVP2Map; 057 import org.deegree.framework.util.StringTools; 058 import org.deegree.framework.xml.InvalidConfigurationException; 059 import org.deegree.framework.xml.XMLFragment; 060 import org.deegree.framework.xml.XMLParsingException; 061 import org.deegree.framework.xml.XMLTools; 062 import org.deegree.framework.xml.XSLTDocument; 063 import org.deegree.model.crs.UnknownCRSException; 064 import org.deegree.model.metadata.iso19115.OnlineResource; 065 import org.deegree.model.spatialschema.Envelope; 066 import org.deegree.model.spatialschema.GMLGeometryAdapter; 067 import org.deegree.model.spatialschema.Geometry; 068 import org.deegree.model.spatialschema.GeometryException; 069 import org.deegree.ogcbase.CommonNamespaces; 070 import org.deegree.ogcwebservices.OGCWebService; 071 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException; 072 import org.deegree.ogcwebservices.getcapabilities.MetadataURL; 073 import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata; 074 import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification; 075 import org.deegree.ogcwebservices.getcapabilities.ServiceProvider; 076 import org.deegree.ogcwebservices.wcs.RemoteWCService; 077 import org.deegree.ogcwebservices.wcs.WCService; 078 import org.deegree.ogcwebservices.wcs.configuration.WCSConfiguration; 079 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities; 080 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument; 081 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage; 082 import org.deegree.ogcwebservices.wfs.WFServiceFactory; 083 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 084 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 085 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration; 086 import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument; 087 import org.deegree.ogcwebservices.wfs.operation.Query; 088 import org.deegree.ogcwebservices.wmps.capabilities.WMPSCapabilitiesDocument; 089 import org.deegree.ogcwebservices.wms.RemoteWMService; 090 import org.deegree.ogcwebservices.wms.capabilities.Attribution; 091 import org.deegree.ogcwebservices.wms.capabilities.AuthorityURL; 092 import org.deegree.ogcwebservices.wms.capabilities.DataURL; 093 import org.deegree.ogcwebservices.wms.capabilities.Dimension; 094 import org.deegree.ogcwebservices.wms.capabilities.Extent; 095 import org.deegree.ogcwebservices.wms.capabilities.FeatureListURL; 096 import org.deegree.ogcwebservices.wms.capabilities.GazetteerParam; 097 import org.deegree.ogcwebservices.wms.capabilities.Identifier; 098 import org.deegree.ogcwebservices.wms.capabilities.Layer; 099 import org.deegree.ogcwebservices.wms.capabilities.LayerBoundingBox; 100 import org.deegree.ogcwebservices.wms.capabilities.LegendURL; 101 import org.deegree.ogcwebservices.wms.capabilities.ScaleHint; 102 import org.deegree.ogcwebservices.wms.capabilities.Style; 103 import org.deegree.ogcwebservices.wms.capabilities.StyleSheetURL; 104 import org.deegree.ogcwebservices.wms.capabilities.StyleURL; 105 import org.deegree.ogcwebservices.wms.capabilities.UserDefinedSymbolization; 106 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 107 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 108 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 109 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource; 110 import org.deegree.ogcwebservices.wms.configuration.LocalWCSDataSource; 111 import org.deegree.ogcwebservices.wms.configuration.LocalWFSDataSource; 112 import org.deegree.ogcwebservices.wms.configuration.RemoteWCSDataSource; 113 import org.deegree.ogcwebservices.wms.configuration.RemoteWFSDataSource; 114 import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource; 115 import org.deegree.ogcwebservices.wms.operation.GetMap; 116 import org.w3c.dom.Element; 117 import org.w3c.dom.Node; 118 import org.xml.sax.SAXException; 119 120 /** 121 * Represents an XML configuration document for a deegree WMPS 1.0 instance, i.e. it consists of all sections common to 122 * an OGC WMS 1.1.1 capabilities document plus a deegree specific section named <code>deegreeParams</code> and... TODO 123 * 124 * @author <a href="mailto:deshmukh@lat-lon.de">Anup Deshmukh</a> 125 * @author last edited by: $Author: mschneider $ 126 * 127 * @version 2.0, $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 128 */ 129 public class WMPSConfigurationDocument extends WMPSCapabilitiesDocument { 130 131 private static final long serialVersionUID = -7940857863171829848L; 132 133 private static final ILogger LOG = LoggerFactory.getLogger( WMPSConfigurationDocument.class ); 134 135 protected static final URI DEEGREEWPSNS = CommonNamespaces.DEEGREEWMPS; 136 137 private static final String XML_TEMPLATE = "WMPSConfigurationTemplate.xml"; 138 139 private static final String XSLT_TEMPLATE_NAME = "WMPSConfigurationTransform.xsl"; 140 141 private static XSLTDocument XSLT_TEMPLATE; 142 143 private static Map<URL, Object> capaCache = new HashMap<URL, Object>(); 144 145 static { 146 XSLT_TEMPLATE = new XSLTDocument(); 147 try { 148 XSLT_TEMPLATE.load( WMPSConfigurationDocument.class.getResource( XSLT_TEMPLATE_NAME ) ); 149 } catch ( Exception e ) { 150 BootLogger.logError( "Error loading XSLT sheet in WMPSConfigurationDocument.", e ); 151 } 152 } 153 154 /** 155 * 156 */ 157 public static void resetCapabilitiesCache() { 158 capaCache.clear(); 159 } 160 161 /** 162 * Creates a skeleton capabilities document that contains the mandatory elements only. 163 * 164 * @throws IOException 165 * @throws SAXException 166 */ 167 @Override 168 public void createEmptyDocument() 169 throws IOException, SAXException { 170 URL url = WMPSConfigurationDocument.class.getResource( XML_TEMPLATE ); 171 if ( url == null ) { 172 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." ); 173 } 174 load( url ); 175 } 176 177 /** 178 * Creates a class representation of the document. 179 * 180 * @return class representation of the configuration document 181 * @throws InvalidConfigurationException 182 */ 183 public WMPSConfiguration parseConfiguration() 184 throws InvalidConfigurationException { 185 186 try { 187 // transform document to fill missing elements and attributes with default values 188 XMLFragment frag = XSLT_TEMPLATE.transform( this ); 189 this.setRootElement( frag.getRootElement() ); 190 } catch ( TransformerException e ) { 191 String msg = "Error transforming WMPS configuration document (in order to fill " + "in default value). " 192 + e.getMessage(); 193 LOG.logError( msg, e ); 194 throw new InvalidConfigurationException( msg, e ); 195 } 196 197 ServiceIdentification serviceIdentification = null; 198 ServiceProvider serviceProvider = null; 199 UserDefinedSymbolization uds = null; 200 OperationsMetadata metadata = null; 201 Layer layer = null; 202 WMPSDeegreeParams params = null; 203 String version = parseVersion(); 204 try { 205 Node node = XMLTools.getRequiredNode( getRootElement(), "deegreewmps:DeegreeParam", nsContext ); 206 params = parseDeegreeParams( node ); 207 serviceIdentification = parseServiceIdentification(); 208 serviceProvider = parseServiceProvider(); 209 uds = parseUserDefinedSymbolization(); 210 metadata = parseOperationsMetadata(); 211 Element layerElem = (Element) XMLTools.getRequiredNode( getRootElement(), "./Capability/Layer", nsContext ); 212 layer = parseLayers( layerElem, null ); 213 } catch ( XMLParsingException e ) { 214 e.printStackTrace(); 215 throw new InvalidConfigurationException( e.getMessage() + StringTools.stackTraceToString( e ) ); 216 } catch ( MalformedURLException e ) { 217 throw new InvalidConfigurationException( e.getMessage() + " - " + StringTools.stackTraceToString( e ) ); 218 } catch ( UnknownCRSException e ) { 219 throw new InvalidConfigurationException( getClass().getName(), e.getMessage() ); 220 } 221 WMPSConfiguration wmpsConfiguration = new WMPSConfiguration( version, serviceIdentification, serviceProvider, 222 uds, metadata, layer, params, getSystemId() ); 223 224 return wmpsConfiguration; 225 } 226 227 /** 228 * Creates a class representation of the <code>deegreeParams</code>- section. 229 * 230 * @param root 231 * @return WMPSDeegreeParams 232 * @throws XMLParsingException 233 * @throws MalformedURLException 234 */ 235 public WMPSDeegreeParams parseDeegreeParams( Node root ) 236 throws XMLParsingException, MalformedURLException { 237 238 String xPath = "./deegreewmps:DefaultOnlineResource"; 239 Element elem = (Element) XMLTools.getRequiredNode( root, xPath, nsContext ); 240 241 OnlineResource ol = parseOnLineResource( elem ); 242 xPath = "./deegreewmps:CacheSize"; 243 int cache = XMLTools.getNodeAsInt( root, xPath, nsContext, 100 ); 244 xPath = "./deegreewmps:MaxLifeTime"; 245 int maxLifeTime = XMLTools.getNodeAsInt( root, xPath, nsContext, 3600 ); 246 xPath = "./deegreewmps:RequestTimeLimit"; 247 int reqTimeLimit = XMLTools.getNodeAsInt( root, xPath, nsContext, 15 ); 248 reqTimeLimit *= 1000; 249 xPath = "./deegreewmps:MapQuality"; 250 double mapQuality = XMLTools.getNodeAsDouble( root, xPath, nsContext, 0.95 ); 251 xPath = "./deegreewmps:MaxMapWidth"; 252 int maxMapWidth = XMLTools.getNodeAsInt( root, xPath, nsContext, 1000 ); 253 xPath = "./deegreewmps:MaxMapHeight"; 254 int maxMapHeight = XMLTools.getNodeAsInt( root, xPath, nsContext, 1000 ); 255 xPath = "./deegreewmps:Copyright"; 256 String copyright = XMLTools.getNodeAsString( root, xPath, nsContext, "" ); 257 URL dtdLocation = null; 258 xPath = "deegreewmps:DTDLocation"; 259 if ( XMLTools.getNode( root, xPath, nsContext ) != null ) { 260 xPath = "./deegreewmps:DTDLocation/deegreewmps:OnlineResource"; 261 elem = (Element) XMLTools.getRequiredNode( root, xPath, nsContext ); 262 OnlineResource olr = parseOnLineResource( elem ); 263 dtdLocation = olr.getLinkage().getHref(); 264 } else { 265 dtdLocation = new URL( "http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" ); 266 } 267 xPath = "./deegreewmps:AntiAliased"; 268 boolean antiAliased = XMLTools.getNodeAsBoolean( root, xPath, nsContext, true ); 269 xPath = "./deegreewmps:GazetteerParameter"; 270 elem = (Element) XMLTools.getNode( root, xPath, nsContext ); 271 GazetteerParam gazetteer = null; 272 if ( elem != null ) { 273 gazetteer = parseGazetteerParameter( elem ); 274 } 275 276 Proxy proxy = parseProxy( root ); 277 278 List<String> synchList = parseSynchTemplates( root ); 279 280 CacheDatabase cacheDatabase = parseCacheDatabase( root ); 281 282 PrintMapParam printMapParam = parsePrintMapParam( root ); 283 284 WMPSDeegreeParams deegreeParams = new WMPSDeegreeParams( cache, maxLifeTime, reqTimeLimit, (float) mapQuality, 285 ol, maxMapWidth, maxMapHeight, antiAliased, copyright, 286 gazetteer, null, dtdLocation, proxy, synchList, 287 cacheDatabase, printMapParam ); 288 289 return deegreeParams; 290 } 291 292 /** 293 * Parse the cache database parameters used by the wmps to store the asynchronous requests. 294 * 295 * @param root 296 * @return CacheDatabase 297 * @throws XMLParsingException 298 */ 299 private CacheDatabase parseCacheDatabase( Node root ) 300 throws XMLParsingException { 301 302 CacheDatabase cacheDatabase = null; 303 String xPath = "./deegreewmps:CacheDatabase"; 304 Node cacheDb = XMLTools.getNode( root, xPath, nsContext ); 305 if ( cacheDb != null ) { 306 xPath = "./deegreewmps:JDBCConnection"; 307 Node jdbcConnection = XMLTools.getRequiredNode( cacheDb, xPath, nsContext ); 308 String driver = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Driver", nsContext ); 309 String url = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Url", nsContext ); 310 String user = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:User", nsContext ); 311 String password = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Password", nsContext ); 312 cacheDatabase = new CacheDatabase( driver, url, user, password ); 313 LOG.logDebug( "Successfully parsed the deegree wmps cache database parameters." ); 314 } 315 316 return cacheDatabase; 317 } 318 319 /** 320 * Parse the PrintMapParam node and retrieve the (jasper reports)template directory, the default template name if 321 * none is specified in the request. Also parse the output directory location and the location of the printed image 322 * output directory. 323 * 324 * @param root 325 * @return PrintMapParam 326 * @throws XMLParsingException 327 * @throws MalformedURLException 328 */ 329 private PrintMapParam parsePrintMapParam( Node root ) 330 throws XMLParsingException, MalformedURLException { 331 332 Node printParam = XMLTools.getRequiredNode( root, "./deegreewmps:PrintMapParam", nsContext ); 333 // set default as pdf 334 String format = XMLTools.getNodeAsString( printParam, "./deegreewmps:Format", nsContext, "pdf" ); 335 Node templ = XMLTools.getRequiredNode( printParam, "./deegreewmps:Template", nsContext ); 336 String templateDirectory = XMLTools.getRequiredNodeAsString( templ, "./deegreewmps:Directory", nsContext ); 337 338 templateDirectory = this.resolve( templateDirectory ).toExternalForm(); 339 if ( !templateDirectory.endsWith( "/" ) ) { 340 templateDirectory = templateDirectory + '/'; 341 } 342 String plotDirectory = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:PlotDirectory", nsContext ); 343 plotDirectory = this.resolve( plotDirectory ).toExternalForm(); 344 String onlineResource = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:OnlineResource", nsContext ); 345 String plotImgDir = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:PlotImageDirectory", nsContext ); 346 plotImgDir = this.resolve( plotImgDir ).toExternalForm(); 347 String adminMail = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:AdministratorEMailAddress", 348 nsContext ); 349 String mailHost = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:MailHost", nsContext ); 350 String mailHostUser = XMLTools.getNodeAsString( printParam, "./deegreewmps:MailHostUser", nsContext, null ); 351 String mailHostPassword = XMLTools.getNodeAsString( printParam, "./deegreewmps:MailHostPassword", nsContext, 352 null ); 353 354 String mailTextTemplate = XMLTools.getNodeAsString( printParam, "./deegreewmps:MailTextTemplate", nsContext, 355 "You can access the printMap result at {1}" ); 356 357 int targetRes = XMLTools.getNodeAsInt( printParam, "./deegreewmps:TargetResolution", nsContext, 300 ); 358 359 return new PrintMapParam( format, templateDirectory, onlineResource, plotDirectory, plotImgDir, adminMail, 360 mailHost, mailHostUser, mailHostPassword, mailTextTemplate, targetRes ); 361 } 362 363 /** 364 * parses the list of templates that shall be handled synchronously 365 * 366 * @param root 367 * @return List 368 * @throws XMLParsingException 369 */ 370 private List<String> parseSynchTemplates( Node root ) 371 throws XMLParsingException { 372 373 String xPath = "./deegreewmps:SynchronousTemplates/deegreewmps:Template"; 374 String[] nodes = XMLTools.getNodesAsStrings( root, xPath, nsContext ); 375 List<String> list = new ArrayList<String>( nodes.length ); 376 for ( int i = 0; i < nodes.length; i++ ) { 377 list.add( nodes[i] ); 378 } 379 380 return list; 381 } 382 383 /** 384 * @param root 385 * @return Proxy 386 * @throws XMLParsingException 387 */ 388 private Proxy parseProxy( Node root ) 389 throws XMLParsingException { 390 391 Proxy proxy = null; 392 Node pro = XMLTools.getNode( root, "./deegreewmps:Proxy", nsContext ); 393 if ( pro != null ) { 394 String proxyHost = XMLTools.getRequiredNodeAsString( pro, "./@proxyHost", nsContext ); 395 String proxyPort = XMLTools.getRequiredNodeAsString( pro, "./@proxyPort", nsContext ); 396 proxy = new Proxy( proxyHost, proxyPort ); 397 } 398 399 return proxy; 400 } 401 402 /** 403 * creates an object that describes the access to a gazetteer if one have been defined at the <DeegreeParam>section 404 * of the capabilities/configuration 405 * 406 * @param element 407 * @return GazetteerParam 408 * @throws XMLParsingException 409 */ 410 private GazetteerParam parseGazetteerParameter( Element element ) 411 throws XMLParsingException { 412 413 GazetteerParam gazetteer = null; 414 415 if ( element != null ) { 416 String xPath = "./deegreewmps:OnlineResource"; 417 Element elem = (Element) XMLTools.getRequiredNode( element, xPath, nsContext ); 418 OnlineResource olr = parseOnLineResource( elem ); 419 URL onlineResource = olr.getLinkage().getHref(); 420 // optional: <LocationRadius>, default: 10 421 double radius = XMLTools.getNodeAsDouble( element, "LocationRadius", nsContext, 10 ); 422 gazetteer = new GazetteerParam( onlineResource, radius ); 423 } 424 425 return gazetteer; 426 } 427 428 /** 429 * returns the layers offered by the WMS 430 * 431 * @param layerElem 432 * @param parent 433 * @return Layer 434 * @throws XMLParsingException 435 * @throws UnknownCRSException 436 */ 437 @Override 438 protected Layer parseLayers( Element layerElem, Layer parent ) 439 throws XMLParsingException, UnknownCRSException { 440 441 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false ); 442 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 ); 443 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false ); 444 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false ); 445 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 ); 446 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 ); 447 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null ); 448 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext ); 449 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null ); 450 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext ); 451 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext ); 452 List<Node> nl = XMLTools.getNodes( layerElem, "./BoundingBox", nsContext ); 453 // substitute with Envelope 454 LayerBoundingBox[] bboxes = null; 455 if ( nl.size() == 0 && parent != null ) { 456 // inherit BoundingBoxes from parent layer 457 bboxes = parent.getBoundingBoxes(); 458 } else { 459 bboxes = parseLayerBoundingBoxes( nl ); 460 } 461 462 Element llBox = (Element) XMLTools.getNode( layerElem, "./LatLonBoundingBox", nsContext ); 463 Envelope llBoundingBox = null; 464 if ( llBox == null && parent != null ) { 465 // inherit LatLonBoundingBox parent layer 466 llBoundingBox = parent.getLatLonBoundingBox(); 467 } else { 468 llBoundingBox = parseLatLonBoundingBox( llBox ); 469 } 470 471 Dimension[] dimensions = parseDimensions( layerElem ); 472 Extent[] extents = parseExtents( layerElem ); 473 Attribution attribution = parseAttribution( layerElem ); 474 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem ); 475 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem ); 476 DataURL[] dataURLs = parseDataURL( layerElem ); 477 Identifier[] identifiers = parseIdentifiers( layerElem ); 478 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem ); 479 Style[] styles = parseStyles( layerElem ); 480 ScaleHint scaleHint = parseScaleHint( layerElem ); 481 AbstractDataSource[] ds = parseDataSources( layerElem, name ); 482 483 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title, 484 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes, 485 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs, 486 featureListURLs, styles, null, ds, parent ); 487 488 // get Child layers 489 nl = XMLTools.getNodes( layerElem, "./Layer", nsContext ); 490 Layer[] layers = new Layer[nl.size()]; 491 for ( int i = 0; i < layers.length; i++ ) { 492 layers[i] = parseLayers( (Element) nl.get( i ), layer ); 493 } 494 // set child layers 495 layer.setLayer( layers ); 496 497 return layer; 498 } 499 500 /** 501 * Parse the Datasources element 502 * 503 * @param layerElem 504 * @param layerName 505 * @return AbstractDataSource[] 506 * @throws XMLParsingException 507 */ 508 private AbstractDataSource[] parseDataSources( Element layerElem, String layerName ) 509 throws XMLParsingException { 510 511 List<Node> nl = XMLTools.getNodes( layerElem, "./deegreewmps:DataSource", nsContext ); 512 513 AbstractDataSource[] ds = new AbstractDataSource[nl.size()]; 514 for ( int i = 0; i < ds.length; i++ ) { 515 516 boolean failOnEx = XMLTools.getNodeAsBoolean( (Node) nl.get( i ), "./@failOnException", nsContext, true ); 517 518 boolean queryable = XMLTools.getNodeAsBoolean( (Node) nl.get( i ), "./@queryable", nsContext, false ); 519 520 QualifiedName name = XMLTools.getNodeAsQualifiedName( (Node) nl.get( i ), "./deegreewmps:Name/text()", 521 nsContext, new QualifiedName( layerName ) ); 522 523 String stype = XMLTools.getRequiredNodeAsString( (Node) nl.get( i ), "./deegreewmps:Type", nsContext ); 524 525 String xPath = "./deegreewmps:OWSCapabilities/deegreewmps:OnlineResource"; 526 Node node = XMLTools.getRequiredNode( (Node) nl.get( i ), xPath, nsContext ); 527 528 URL url = parseOnLineResource( (Element) node ).getLinkage().getHref(); 529 ScaleHint scaleHint = parseScaleHint( (Node) nl.get( i ) ); 530 Geometry validArea = parseValidArea( (Node) nl.get( i ) ); 531 532 try { 533 if ( "LOCALWFS".equals( stype ) ) { 534 ds[i] = createLocalWFSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint, 535 validArea, 60 ); 536 } else if ( "LOCALWCS".equals( stype ) ) { 537 ds[i] = createLocalWCSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint, 538 validArea, 60 ); 539 } else if ( "REMOTEWFS".equals( stype ) ) { 540 ds[i] = createRemoteWFSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint, 541 validArea, 60 ); 542 } else if ( "REMOTEWCS".equals( stype ) ) { 543 ds[i] = createRemoteWCSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint, 544 validArea, 60 ); 545 } else if ( "REMOTEWMS".equals( stype ) ) { 546 ds[i] = createRemoteWMSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint, 547 validArea, 60 ); 548 } else { 549 throw new XMLParsingException( "invalid DataSource type: " + stype + " defined in deegree WMS " 550 + "configuration for DataSource: " + name ); 551 } 552 } catch ( Exception e ) { 553 throw new XMLParsingException( "could not create service instance for " + "WMPS datasource: " + name, e ); 554 } 555 } 556 557 return ds; 558 } 559 560 /** 561 * returns the area a data source is valid. If the optional element <ValidArea>is not defined in the configuration 562 * returns <code>null</code>. 563 * 564 * @param node 565 * @return Geometry 566 * @throws XMLParsingException 567 */ 568 private Geometry parseValidArea( Node node ) 569 throws XMLParsingException { 570 571 Geometry geom = null; 572 List<Node> nl = XMLTools.getNodes( node, "./deegreewmps:ValidArea/*", nsContext ); 573 if ( node != null ) { 574 try { 575 for ( int i = 0; i < nl.size(); i++ ) { 576 if ( nl.get( 0 ).getNamespaceURI().equals( GMLNS ) ) { 577 geom = GMLGeometryAdapter.wrap( (Element) nl.get( 0 ), null ); 578 break; 579 } 580 } 581 } catch ( GeometryException e ) { 582 throw new XMLParsingException( "couldn't parse/create valid area of a " + "datasource", e ); 583 } 584 } 585 586 return geom; 587 } 588 589 /** 590 * Create a RemoteWMS datasource. 591 * 592 * @param node 593 * @param failOnEx 594 * @param queryable 595 * @param name 596 * @param url 597 * @param scaleHint 598 * @param validArea 599 * @param reqTimeLimit 600 * @return XMLParsingException 601 * @throws Exception 602 */ 603 private RemoteWMSDataSource createRemoteWMSDataSource( Node node, boolean failOnEx, boolean queryable, 604 QualifiedName name, URL url, ScaleHint scaleHint, 605 Geometry validArea, int reqTimeLimit ) 606 throws Exception { 607 608 int type = AbstractDataSource.REMOTEWMS; 609 String xPath = "./deegreewmps:FeatureInfoTransformation/deegreewmps:OnlineResource"; 610 Node fitNode = XMLTools.getNode( node, xPath, nsContext ); 611 URL fitURL = null; 612 if ( fitNode != null ) { 613 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref(); 614 } 615 616 GetMap getMap = parseWMSFilterCondition( node ); 617 Color[] colors = parseTransparentColors( node ); 618 WMSCapabilities wCapa = null; 619 try { 620 if ( capaCache.get( url ) != null ) { 621 wCapa = (WMSCapabilities) capaCache.get( url ); 622 } else { 623 WMSCapabilitiesDocument doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( url ); 624 wCapa = (WMSCapabilities) doc.parseCapabilities(); 625 capaCache.put( url, wCapa ); 626 } 627 } catch ( Exception e ) { 628 LOG.logError( "could not connet: " + url, e ); 629 } 630 OGCWebService ows = new RemoteWMService( wCapa ); 631 632 // parse added/passed parameter map/list 633 Node vendor = XMLTools.getNode( node, 634 "deegreewmps:FilterCondition/deegreewmps:VendorspecificParameterDefinition", 635 nsContext ); 636 637 List<String> passedParameters = parsePassedParameters( vendor ); 638 Map<String, String> addedParameters = parseAddedParameters( vendor ); 639 640 return new RemoteWMSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getMap, 641 colors, fitURL, reqTimeLimit, passedParameters, addedParameters ); 642 } 643 644 /** 645 * @param vendor 646 * @return the parsed list 647 * @throws XMLParsingException 648 */ 649 private static List<String> parsePassedParameters( Node vendor ) 650 throws XMLParsingException { 651 List<String> passedParameters = new ArrayList<String>( 10 ); 652 653 if ( vendor == null ) { 654 return passedParameters; 655 } 656 657 List<Node> nl = XMLTools.getNodes( vendor, "deegreewmps:PassedVendorspecificParameter/deegreewmps:Name", 658 nsContext ); 659 660 for ( Object obj : nl ) { 661 passedParameters.add( ( (Node) obj ).getTextContent().toUpperCase() ); 662 } 663 664 return passedParameters; 665 } 666 667 /** 668 * @param vendor 669 * @return the parsed map 670 * @throws XMLParsingException 671 */ 672 private static Map<String, String> parseAddedParameters( Node vendor ) 673 throws XMLParsingException { 674 Map<String, String> addedParameters = new HashMap<String, String>( 10 ); 675 676 if ( vendor == null ) { 677 return addedParameters; 678 } 679 680 List<Node> nl = XMLTools.getNodes( 681 vendor, 682 "deegreewmps:AddedVendorspecificParameter/deegreewmps:VendorspecificParameter", 683 nsContext ); 684 685 for ( Object obj : nl ) { 686 String pName = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewmps:Name", nsContext ); 687 String pValue = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewmps:Value", nsContext ); 688 689 addedParameters.put( pName, pValue ); 690 } 691 return addedParameters; 692 } 693 694 /** 695 * Create a Remote WFS datasource. 696 * 697 * @param node 698 * @param failOnEx 699 * @param queryable 700 * @param name 701 * @param url 702 * @param scaleHint 703 * @param validArea 704 * @param reqTimeLimit 705 * @return RemoteWFSDataSource 706 * @throws Exception 707 */ 708 private RemoteWFSDataSource createRemoteWFSDataSource( Node node, boolean failOnEx, boolean queryable, 709 QualifiedName name, URL url, ScaleHint scaleHint, 710 Geometry validArea, int reqTimeLimit ) 711 throws Exception { 712 713 int type = AbstractDataSource.REMOTEWFS; 714 String xPath = "./deegreewmps:FeatureInfoTransformation/deegreewmps:OnlineResource"; 715 Node fitNode = XMLTools.getNode( node, xPath, nsContext ); 716 URL fitURL = null; 717 if ( fitNode != null ) { 718 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref(); 719 } 720 Query query = parseWFSFilterCondition( node ); 721 722 WFSCapabilities wfsCapa = null; 723 if ( capaCache.get( url ) != null ) { 724 wfsCapa = (WFSCapabilities) capaCache.get( url ); 725 } else { 726 WFSCapabilitiesDocument wfsDoc = new WFSCapabilitiesDocument(); 727 wfsDoc.load( url ); 728 wfsCapa = (WFSCapabilities) wfsDoc.parseCapabilities(); 729 capaCache.put( url, wfsCapa ); 730 } 731 // OGCWebService ows = new RemoteWFService( wfsCapa ); 732 OGCWebService ows = null; 733 xPath = "./deegreewmps:GeometryProperty/text()"; 734 QualifiedName geom = new QualifiedName( "app", "GEOM", new URI( "http://www.deegree.org/app" ) ); 735 QualifiedName geoProp = XMLTools.getNodeAsQualifiedName( node, xPath, nsContext, geom ); 736 737 return new RemoteWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, 738 query, fitURL, reqTimeLimit ); 739 740 } 741 742 /** 743 * Create a Local WCS Datasource 744 * 745 * @param node 746 * @param failOnEx 747 * @param queryable 748 * @param name 749 * @param url 750 * @param scaleHint 751 * @param validArea 752 * @param reqTimeLimit 753 * @return RemoteWFSDataSource 754 * @throws Exception 755 */ 756 private LocalWCSDataSource createLocalWCSDataSource( Node node, boolean failOnEx, boolean queryable, 757 QualifiedName name, URL url, ScaleHint scaleHint, 758 Geometry validArea, int reqTimeLimit ) 759 throws Exception { 760 761 int type = AbstractDataSource.LOCALWCS; 762 GetCoverage getCoverage = parseWCSFilterCondition( node ); 763 Color[] colors = parseTransparentColors( node ); 764 WCSConfiguration configuration = null; 765 if ( capaCache.get( url ) != null ) { 766 configuration = (WCSConfiguration) capaCache.get( url ); 767 } else { 768 configuration = WCSConfiguration.create( url ); 769 capaCache.put( url, configuration ); 770 } 771 772 OGCWebService ows = new WCService( configuration ); 773 774 return new LocalWCSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getCoverage, 775 colors, reqTimeLimit ); 776 } 777 778 /** 779 * 780 * @param node 781 * @param failOnEx 782 * @param queryable 783 * @param name 784 * @param url 785 * @param scaleHint 786 * @param validArea 787 * @param i 788 * @return 789 * @throws XMLParsingException 790 * @throws SAXException 791 * @throws IOException 792 * @throws org.deegree.ogcwebservices.wcs.configuration.InvalidConfigurationException 793 * @throws InvalidCapabilitiesException 794 */ 795 private AbstractDataSource createRemoteWCSDataSource( Node node, boolean failOnEx, boolean queryable, 796 QualifiedName name, URL url, ScaleHint scaleHint, 797 Geometry validArea, int reqTimeLimit ) 798 throws XMLParsingException, InvalidCapabilitiesException, IOException, SAXException { 799 int type = AbstractDataSource.REMOTEWCS; 800 801 GetCoverage getCoverage = parseWCSFilterCondition( node ); 802 Color[] colors = parseTransparentColors( node ); 803 WCSCapabilities capabilities = null; 804 if ( capaCache.get( url ) != null ) { 805 capabilities = (WCSCapabilities) capaCache.get( url ); 806 } else { 807 WCSCapabilitiesDocument doc = new WCSCapabilitiesDocument(); 808 doc.load( url ); 809 capabilities = (WCSCapabilities) doc.parseCapabilities(); 810 capaCache.put( url, capabilities ); 811 } 812 813 OGCWebService ows = new RemoteWCService( capabilities ); 814 815 return new RemoteWCSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getCoverage, 816 colors, reqTimeLimit ); 817 818 } 819 820 /** 821 * Create a Local WFS Datasource 822 * 823 * @param node 824 * @param failOnEx 825 * @param queryable 826 * @param name 827 * @param url 828 * @param scaleHint 829 * @param validArea 830 * @param reqTimeLimit 831 * @return LocalWFSDataSource 832 * @throws Exception 833 */ 834 private LocalWFSDataSource createLocalWFSDataSource( Node node, boolean failOnEx, boolean queryable, 835 QualifiedName name, URL url, ScaleHint scaleHint, 836 Geometry validArea, int reqTimeLimit ) 837 throws Exception { 838 839 int type = AbstractDataSource.LOCALWFS; 840 String xPath = null; 841 Query query = parseWFSFilterCondition( node ); 842 WFSConfiguration wfsCapa = null; 843 if ( capaCache.get( url ) != null ) { 844 wfsCapa = (WFSConfiguration) capaCache.get( url ); 845 } else { 846 WFSConfigurationDocument wfsDoc = new WFSConfigurationDocument(); 847 wfsDoc.load( url ); 848 wfsCapa = wfsDoc.getConfiguration(); 849 capaCache.put( url, wfsCapa ); 850 } 851 // OGCWebService ows = WFServiceFactory.getUncachedService( wfsCapa ); 852 OGCWebService ows = WFServiceFactory.createInstance( wfsCapa ); 853 854 QualifiedName geom = new QualifiedName( "app", "GEOM", new URI( "http://www.deegree.org/app" ) ); 855 xPath = "./deegreewmps:GeometryProperty/text()"; 856 QualifiedName geoProp = XMLTools.getNodeAsQualifiedName( node, xPath, nsContext, geom ); 857 858 return new LocalWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, query, 859 null, reqTimeLimit ); 860 } 861 862 /** 863 * Parse trasparent colors. 864 * 865 * @param node 866 * @return Color[] 867 * @throws XMLParsingException 868 */ 869 private Color[] parseTransparentColors( Node node ) 870 throws XMLParsingException { 871 872 String xPath = "./deegreewmps:TransparentColors/deegreewmps:Color"; 873 List<Node> clnl = XMLTools.getNodes( node, xPath, nsContext ); 874 Color[] colors = new Color[clnl.size()]; 875 for ( int i = 0; i < colors.length; i++ ) { 876 colors[i] = Color.decode( XMLTools.getStringValue( (Node) clnl.get( i ) ) ); 877 } 878 879 return colors; 880 } 881 882 /** 883 * Parse Scale hint 884 * 885 * @param node 886 * @return ScaleHint 887 * @throws XMLParsingException 888 */ 889 private ScaleHint parseScaleHint( Node node ) 890 throws XMLParsingException { 891 892 String xPath = "./deegreewmps:ScaleHint/@min"; 893 double minScale = XMLTools.getNodeAsDouble( node, xPath, nsContext, 0 ); 894 xPath = "./deegreewmps:ScaleHint/@max"; 895 double maxScale = XMLTools.getNodeAsDouble( node, xPath, nsContext, Double.MAX_VALUE ); 896 897 return new ScaleHint( minScale, maxScale ); 898 } 899 900 /** 901 * Parse WFS Filter condition 902 * 903 * @param node 904 * @return Query 905 * @throws XMLParsingException 906 */ 907 private Query parseWFSFilterCondition( Node node ) 908 throws XMLParsingException { 909 910 Query query = null; 911 String xPath = "./deegreewmps:FilterCondition/wfs:Query"; 912 Node queryNode = XMLTools.getNode( node, xPath, nsContext ); 913 if ( queryNode != null ) { 914 try { 915 query = Query.create( (Element) queryNode ); 916 } catch ( Exception e ) { 917 throw new XMLParsingException( StringTools.stackTraceToString( e ) ); 918 } 919 } 920 921 return query; 922 } 923 924 /** 925 * Parse WCS Filter Condition 926 * 927 * @param node 928 * @return GetCoverage 929 * @throws XMLParsingException 930 */ 931 private GetCoverage parseWCSFilterCondition( Node node ) 932 throws XMLParsingException { 933 934 GetCoverage getCoverage = null; 935 936 String id = "" + IDGenerator.getInstance().generateUniqueID(); 937 938 StringBuffer sd = new StringBuffer( 1000 ); 939 sd.append( "version=1.0.0&Coverage=%default%&" ); 940 sd.append( "CRS=EPSG:4326&BBOX=0,0,1,1&Width=1" ); 941 sd.append( "&Height=1&Format=%default%&" ); 942 String xPath = "./deegreewmps:FilterCondition/deegreewmps:WCSRequest"; 943 String s = XMLTools.getNodeAsString( node, xPath, nsContext, "" ); 944 sd.append( s ); 945 try { 946 getCoverage = GetCoverage.create( id, sd.toString() ); 947 } catch ( Exception e ) { 948 throw new XMLParsingException( "could not create GetCoverage from WMS " + "FilterCondition", e ); 949 } 950 951 return getCoverage; 952 } 953 954 /** 955 * Returns a GetMap instance , parsing the WMS Filter condition 956 * 957 * @param node 958 * @return GetMap 959 * @throws XMLParsingException 960 */ 961 private GetMap parseWMSFilterCondition( Node node ) 962 throws XMLParsingException { 963 964 GetMap getMap = null; 965 966 String id = "" + IDGenerator.getInstance().generateUniqueID(); 967 968 StringBuffer sd = new StringBuffer( 1000 ); 969 sd.append( "REQUEST=GetMap&LAYERS=%default%&" ); 970 sd.append( "STYLES=&SRS=EPSG:4326&BBOX=0,0,1,1&WIDTH=1&" ); 971 sd.append( "HEIGHT=1&FORMAT=%default%" ); 972 Map<String, String> map1 = KVP2Map.toMap( sd.toString() ); 973 String xPath = "./deegreewmps:FilterCondition/deegreewmps:WMSRequest"; 974 String s = XMLTools.getRequiredNodeAsString( node, xPath, nsContext ); 975 Map<String, String> map2 = KVP2Map.toMap( s ); 976 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) { 977 map2.put( "VERSION", "1.1.1" ); 978 } 979 // if no service is set use WMS as default 980 if ( map2.get( "SERVICE" ) == null ) { 981 map2.put( "SERVICE", "WMS" ); 982 } 983 map1.putAll( map2 ); 984 try { 985 map1.put( "ID", id ); 986 getMap = GetMap.create( map1 ); 987 } catch ( Exception e ) { 988 throw new XMLParsingException( "could not create GetCoverage from WMS " + "FilterCondition", e ); 989 } 990 991 return getMap; 992 } 993 994 /** 995 * Returns a list of Style elements, parsing the style element 996 * 997 * @param layerElem 998 * @return Style[] 999 * @throws XMLParsingException 1000 */ 1001 @Override 1002 protected Style[] parseStyles( Element layerElem ) 1003 throws XMLParsingException { 1004 1005 List<Node> nl = XMLTools.getNodes( layerElem, "./Style", nsContext ); 1006 Style[] styles = new Style[nl.size()]; 1007 for ( int i = 0; i < styles.length; i++ ) { 1008 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Name", nsContext ); 1009 String title = XMLTools.getNodeAsString( nl.get( i ), "./Title", nsContext, null ); 1010 String styleAbstract = XMLTools.getNodeAsString( nl.get( i ), "./Abstract", nsContext, null ); 1011 LegendURL[] legendURLs = parseLegendURL( nl.get( i ) ); 1012 StyleURL styleURL = parseStyleURL( nl.get( i ) ); 1013 StyleSheetURL styleSheetURL = parseStyleSheetURL( nl.get( i ) ); 1014 String xPath = "deegreewmps:StyleResource"; 1015 String styleResource = XMLTools.getNodeAsString( nl.get( i ), xPath, nsContext, "styles.xml" ); 1016 URL sr = null; 1017 try { 1018 sr = resolve( styleResource ); 1019 } catch ( MalformedURLException e ) { 1020 throw new XMLParsingException( "could not parse style resource of " + "style: " + name, e ); 1021 } 1022 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, sr ); 1023 } 1024 1025 return styles; 1026 } 1027 1028 }