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