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