001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/configuration/WMSConfigurationDocument.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2007 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.wms.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.Arrays; 052 import java.util.HashMap; 053 import java.util.List; 054 import java.util.Map; 055 056 import javax.xml.transform.TransformerException; 057 058 import org.deegree.datatypes.QualifiedName; 059 import org.deegree.enterprise.Proxy; 060 import org.deegree.framework.log.ILogger; 061 import org.deegree.framework.log.LoggerFactory; 062 import org.deegree.framework.util.BootLogger; 063 import org.deegree.framework.util.IDGenerator; 064 import org.deegree.framework.util.KVP2Map; 065 import org.deegree.framework.util.StringTools; 066 import org.deegree.framework.xml.InvalidConfigurationException; 067 import org.deegree.framework.xml.XMLFragment; 068 import org.deegree.framework.xml.XMLParsingException; 069 import org.deegree.framework.xml.XMLTools; 070 import org.deegree.framework.xml.XSLTDocument; 071 import org.deegree.i18n.Messages; 072 import org.deegree.model.crs.UnknownCRSException; 073 import org.deegree.model.metadata.iso19115.OnlineResource; 074 import org.deegree.model.spatialschema.Envelope; 075 import org.deegree.model.spatialschema.GMLGeometryAdapter; 076 import org.deegree.model.spatialschema.Geometry; 077 import org.deegree.model.spatialschema.GeometryException; 078 import org.deegree.ogcbase.CommonNamespaces; 079 import org.deegree.ogcwebservices.OGCWebService; 080 import org.deegree.ogcwebservices.getcapabilities.MetadataURL; 081 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 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.RemoteWFService; 086 import org.deegree.ogcwebservices.wfs.WFServiceFactory; 087 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 088 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 089 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration; 090 import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument; 091 import org.deegree.ogcwebservices.wfs.operation.Query; 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.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.operation.GetMap; 111 import org.deegree.owscommon_new.OperationsMetadata; 112 import org.deegree.owscommon_new.ServiceIdentification; 113 import org.deegree.owscommon_new.ServiceProvider; 114 import org.w3c.dom.Element; 115 import org.w3c.dom.Node; 116 import org.xml.sax.SAXException; 117 118 /** 119 * <code>WMSConfigurationDocument</code> is the parser class for a standard 1.1.1 WMS 120 * configuration document, ie, a capabilities document enriched by deegree parameters. 121 * 122 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a> 123 * @author last edited by: $Author: aschmitz $ 124 * 125 * @version 2.0, $Revision: 8112 $, $Date: 2007-09-05 14:57:09 +0200 (Mi, 05 Sep 2007) $ 126 * 127 * @since 2.0 128 */ 129 public class WMSConfigurationDocument extends WMSCapabilitiesDocument { 130 131 private static final long serialVersionUID = 2320990982989322325L; 132 133 protected static final URI DEEGREEWMSNS = CommonNamespaces.DEEGREEWMS; 134 135 private static final String XML_TEMPLATE = "WMSConfigurationTemplate.xml"; 136 137 private static final String XSLT_TEMPLATE_NAME = "WMSConfigurationTransform.xsl"; 138 139 private static XSLTDocument XSLT_TEMPLATE; 140 141 private static Map<URL, OGCCapabilities> capaCache = new HashMap<URL, OGCCapabilities>(); 142 143 private static final ILogger LOG = LoggerFactory.getLogger( WMSConfigurationDocument.class ); 144 145 private static final QualifiedName DEFAULT_GEO_PROP = new QualifiedName( 146 "app", 147 "GEOM", 148 CommonNamespaces.buildNSURI( "http://www.deegree.org/app" ) ); 149 150 static { 151 XSLT_TEMPLATE = new XSLTDocument(); 152 try { 153 XSLT_TEMPLATE.load( WMSConfigurationDocument.class.getResource( XSLT_TEMPLATE_NAME ) ); 154 } catch ( Exception e ) { 155 BootLogger.logError( "Error loading XSLT sheet in WMSConfigurationDocument.", e ); 156 } 157 } 158 159 /** 160 * Creates a skeleton capabilities document that contains the mandatory elements only. 161 * 162 * @throws IOException 163 * @throws SAXException 164 */ 165 @Override 166 public void createEmptyDocument() 167 throws IOException, SAXException { 168 URL url = WMSConfigurationDocument.class.getResource( XML_TEMPLATE ); 169 if ( url == null ) { 170 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." ); 171 } 172 load( url ); 173 } 174 175 /** 176 * Creates a class representation of the document. 177 * 178 * @return class representation of the configuration document 179 * @throws InvalidConfigurationException 180 */ 181 public WMSConfiguration parseConfiguration() 182 throws InvalidConfigurationException { 183 184 try { 185 // transform document to fill missing elements and attributes with 186 // default values 187 XMLFragment frag = XSLT_TEMPLATE.transform( this ); 188 this.setRootElement( frag.getRootElement() ); 189 } catch ( TransformerException e ) { 190 String msg = Messages.getMessage( "WMS_CONFIGURATION_TRANSFORM" ); 191 LOG.logError( msg, e ); 192 throw new InvalidConfigurationException( msg, e ); 193 } 194 195 ServiceIdentification serviceIdentification = null; 196 ServiceProvider serviceProvider = null; 197 OperationsMetadata metadata = null; 198 Layer layer = null; 199 UserDefinedSymbolization uds = null; 200 WMSDeegreeParams params = null; 201 Element root = getRootElement(); 202 String version = root.getAttribute( "version" ); 203 String updateSeq = root.getAttribute( "updateSequence" ); 204 try { 205 Node node = XMLTools.getRequiredNode( getRootElement(), "./deegreewms:DeegreeParam", nsContext ); 206 params = parseDeegreeParams( node ); 207 208 serviceIdentification = parseServiceIdentification(); 209 serviceProvider = parseServiceProvider(); 210 metadata = parseOperationsMetadata(); 211 212 uds = parseUserDefinedSymbolization(); 213 Element layerElem = (Element) XMLTools.getRequiredNode( getRootElement(), "./Capability/Layer", nsContext ); 214 layer = parseLayers( layerElem, null, null ); 215 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( e.getMessage() + " - " + StringTools.stackTraceToString( e ) ); 223 } 224 225 WMSConfiguration wmsConfiguration = new WMSConfiguration( version, updateSeq, serviceIdentification, 226 serviceProvider, uds, metadata, layer, params, 227 getSystemId() ); 228 229 return wmsConfiguration; 230 } 231 232 /** 233 * Creates a class representation of the <code>deegreeParams</code>- section. 234 * 235 * @param root 236 * 237 * @return the deegree params 238 * @throws XMLParsingException 239 * @throws MalformedURLException 240 */ 241 public WMSDeegreeParams parseDeegreeParams( Node root ) 242 throws XMLParsingException, MalformedURLException { 243 244 Element elem = (Element) XMLTools.getRequiredNode( root, "./deegreewms:DefaultOnlineResource", nsContext ); 245 OnlineResource ol = parseOnLineResource( elem ); 246 int cache = XMLTools.getNodeAsInt( root, "./deegreewms:CacheSize", nsContext, 100 ); 247 int maxLifeTime = XMLTools.getNodeAsInt( root, "./deegreewms:MaxLifeTime", nsContext, 3600 ); 248 int reqTimeLimit = XMLTools.getNodeAsInt( root, "./deegreewms:RequestTimeLimit", nsContext, 15 ); 249 reqTimeLimit *= 1000; 250 double mapQuality = XMLTools.getNodeAsDouble( root, "./deegreewms:MapQuality", nsContext, 0.95 ); 251 int maxMapWidth = XMLTools.getNodeAsInt( root, "./deegreewms:MaxMapWidth", nsContext, 1000 ); 252 int maxMapHeight = XMLTools.getNodeAsInt( root, "./deegreewms:MaxMapHeight", nsContext, 1000 ); 253 int featureInfoRadius = XMLTools.getNodeAsInt( root, "./deegreewms:FeatureInfoRadius", nsContext, 5 ); 254 String copyright = XMLTools.getNodeAsString( root, "./deegreewms:Copyright", nsContext, "" ); 255 256 URL dtdLocation = null; 257 if ( XMLTools.getNode( root, "deegreewms:DTDLocation", nsContext ) != null ) { 258 elem = (Element) XMLTools.getRequiredNode( root, "./deegreewms:DTDLocation/deegreewms:OnlineResource", 259 nsContext ); 260 OnlineResource olr = parseOnLineResource( elem ); 261 dtdLocation = olr.getLinkage().getHref(); 262 } else { 263 dtdLocation = new URL( "http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" ); 264 } 265 266 URL featureSchemaLocation = null; 267 String featureSchemaNamespace = null; 268 if ( XMLTools.getNode( root, "deegreewms:FeatureInfoSchema", nsContext ) != null ) { 269 featureSchemaNamespace = XMLTools.getRequiredNodeAsString( 270 root, 271 "deegreewms:FeatureInfoSchema/deegreewms:Namespace", 272 nsContext ); 273 elem = (Element) XMLTools.getRequiredNode( root, "deegreewms:FeatureInfoSchema/deegreewms:OnlineResource", 274 nsContext ); 275 OnlineResource link = parseOnLineResource( elem ); 276 featureSchemaLocation = link.getLinkage().getHref(); 277 } 278 279 boolean antiAliased = XMLTools.getNodeAsBoolean( root, "./deegreewms:AntiAliased", nsContext, true ); 280 281 Proxy proxy = parseProxy( root ); 282 283 List<String> supportedVersions = parseSupportedVersions( root ); 284 285 WMSDeegreeParams deegreeParams = new WMSDeegreeParams( cache, maxLifeTime, reqTimeLimit, (float) mapQuality, 286 ol, maxMapWidth, maxMapHeight, antiAliased, 287 featureInfoRadius, copyright, null, dtdLocation, proxy, 288 supportedVersions, featureSchemaLocation, 289 featureSchemaNamespace ); 290 291 return deegreeParams; 292 } 293 294 // returns the list of supported versions 295 private List<String> parseSupportedVersions( Node root ) 296 throws XMLParsingException { 297 298 String[] versions = XMLTools.getNodesAsStrings( root, "./deegreewms:SupportedVersion", nsContext ); 299 300 if ( versions != null ) 301 return Arrays.asList( versions ); 302 303 return new ArrayList<String>(); 304 305 } 306 307 /** 308 * @param root 309 * @return the proxy 310 * @throws XMLParsingException 311 */ 312 private Proxy parseProxy( Node root ) 313 throws XMLParsingException { 314 315 Proxy proxy = null; 316 Node pro = XMLTools.getNode( root, "./deegreewms:Proxy", nsContext ); 317 if ( pro != null ) { 318 String proxyHost = XMLTools.getRequiredNodeAsString( pro, "./@proxyHost", nsContext ); 319 String proxyPort = XMLTools.getRequiredNodeAsString( pro, "./@proxyPort", nsContext ); 320 proxy = new Proxy( proxyHost, proxyPort ); 321 } 322 323 return proxy; 324 } 325 326 /** 327 * returns the layers offered by the WMS 328 * 329 * @throws XMLParsingException 330 * @throws UnknownCRSException 331 */ 332 @Override 333 protected Layer parseLayers( Element layerElem, Layer parent, ScaleHint scaleHint ) 334 throws XMLParsingException, UnknownCRSException { 335 336 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false ); 337 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 ); 338 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false ); 339 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false ); 340 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 ); 341 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 ); 342 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null ); 343 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext ); 344 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null ); 345 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext ); 346 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext ); 347 348 List<Element> nl = XMLTools.getElements( layerElem, "./BoundingBox", nsContext ); 349 // TODO 350 // substitue with Envelope 351 LayerBoundingBox[] bboxes = null; 352 if ( nl.size() == 0 && parent != null ) { 353 // inherit BoundingBoxes from parent layer 354 bboxes = parent.getBoundingBoxes(); 355 } else { 356 bboxes = parseLayerBoundingBoxes( nl ); 357 } 358 359 Element llBox = (Element) XMLTools.getNode( layerElem, "./LatLonBoundingBox", nsContext ); 360 Envelope llBoundingBox = null; 361 if ( llBox == null && parent != null ) { 362 // inherit LatLonBoundingBox parent layer 363 llBoundingBox = parent.getLatLonBoundingBox(); 364 } else { 365 llBoundingBox = parseLatLonBoundingBox( llBox ); 366 } 367 368 Dimension[] dimensions = parseDimensions( layerElem ); 369 Extent[] extents = parseExtents( layerElem ); 370 371 Attribution attribution = parseAttribution( layerElem ); 372 373 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem ); 374 375 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem ); 376 377 DataURL[] dataURLs = parseDataURL( layerElem ); 378 379 Identifier[] identifiers = parseIdentifiers( layerElem ); 380 381 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem ); 382 383 Style[] styles = parseStyles( layerElem ); 384 385 scaleHint = parseScaleHint( layerElem, scaleHint ); 386 387 AbstractDataSource[] ds = parseDataSources( layerElem, name, scaleHint ); 388 389 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title, 390 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes, 391 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs, 392 featureListURLs, styles, null, ds, parent ); 393 394 // get Child layers 395 nl = XMLTools.getElements( layerElem, "./Layer", nsContext ); 396 Layer[] layers = new Layer[nl.size()]; 397 for ( int i = 0; i < layers.length; i++ ) { 398 layers[i] = parseLayers( nl.get( i ), layer, scaleHint ); 399 } 400 401 // set child layers 402 layer.setLayer( layers ); 403 404 return layer; 405 } 406 407 /** 408 * 409 * @param layerElem 410 * @return the data sources 411 * @throws XMLParsingException 412 */ 413 protected AbstractDataSource[] parseDataSources( Element layerElem, String layerName, ScaleHint scaleHint ) 414 throws XMLParsingException { 415 416 List<Node> nl = XMLTools.getNodes( layerElem, "./deegreewms:DataSource", nsContext ); 417 418 AbstractDataSource[] ds = new AbstractDataSource[nl.size()]; 419 for ( int i = 0; i < ds.length; i++ ) { 420 boolean failOnEx = XMLTools.getNodeAsBoolean( nl.get( i ), "./@failOnException", nsContext, true ); 421 boolean queryable = XMLTools.getNodeAsBoolean( nl.get( i ), "./@queryable", nsContext, false ); 422 QualifiedName name = XMLTools.getNodeAsQualifiedName( nl.get( i ), "./deegreewms:Name/text()", nsContext, 423 new QualifiedName( layerName ) ); 424 String stype = XMLTools.getRequiredNodeAsString( nl.get( i ), "./deegreewms:Type", nsContext ); 425 426 int reqTimeLimit = XMLTools.getNodeAsInt( nl.get( i ), "./deegreewms:RequestTimeLimit/text()", nsContext, 427 30 ); 428 429 scaleHint = parseDSScaleHint( (Element) nl.get( i ), scaleHint ); 430 431 String s = "./deegreewms:OWSCapabilities/deegreewms:OnlineResource"; 432 Node node = XMLTools.getRequiredNode( nl.get( i ), s, nsContext ); 433 434 URL url = parseOnLineResource( (Element) node ).getLinkage().getHref(); 435 436 Geometry validArea = parseValidArea( nl.get( i ) ); 437 438 try { 439 if ( "LOCALWFS".equals( stype ) ) { 440 ds[i] = createLocalWFSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint, 441 validArea, reqTimeLimit ); 442 } else if ( "LOCALWCS".equals( stype ) ) { 443 ds[i] = createLocalWCSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint, 444 validArea, reqTimeLimit ); 445 } else if ( "REMOTEWFS".equals( stype ) ) { 446 ds[i] = createRemoteWFSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint, 447 validArea, reqTimeLimit ); 448 } else if ( "REMOTEWCS".equals( stype ) ) { 449 // int type = AbstractDataSource.REMOTEWCS; 450 // GetCoverage getCoverage = 451 parseWCSFilterCondition( nl.get( i ) ); 452 // Color[] colors = 453 parseTransparentColors( nl.get( i ) ); 454 // TODO 455 throw new XMLParsingException( "REMOTEWCS is not supported yet!" ); 456 } else if ( "REMOTEWMS".equals( stype ) ) { 457 ds[i] = createRemoteWMSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint, 458 validArea, reqTimeLimit ); 459 } else { 460 throw new XMLParsingException( "invalid DataSource type: " + stype + " defined " 461 + "in deegree WMS configuration for DataSource: " + name ); 462 } 463 } catch ( Exception e ) { 464 LOG.logError( e.getMessage(), e ); 465 throw new XMLParsingException( "could not create service instance for WMS " + "datasource: " + name, e ); 466 } 467 } 468 469 return ds; 470 } 471 472 /** 473 * parses the ScaleHint for a Datasource 474 * 475 * @param layerElem 476 * @param scaleHint 477 * @return the scale hint for the datasource 478 * @throws XMLParsingException 479 */ 480 protected ScaleHint parseDSScaleHint( Element layerElem, ScaleHint scaleHint ) 481 throws XMLParsingException { 482 483 Node scNode = XMLTools.getNode( layerElem, "./deegreewms:ScaleHint", nsContext ); 484 if ( scNode != null ) { 485 double mn = XMLTools.getNodeAsDouble( scNode, "./@min", nsContext, 0 ); 486 double mx = XMLTools.getNodeAsDouble( scNode, "./@max", nsContext, Double.MAX_VALUE ); 487 scaleHint = new ScaleHint( mn, mx ); 488 } 489 490 if ( scaleHint == null ) { 491 // set default value to avoid NullPointerException 492 // when accessing a layers scalehint 493 scaleHint = new ScaleHint( 0, Double.MAX_VALUE ); 494 } 495 496 return scaleHint; 497 } 498 499 /** 500 * returns the area a data source is valid. If the optional element <ValidArea>is not defined in 501 * the configuration <code>null</code>. 502 * 503 * @param node 504 * @return the geometry 505 * @throws Exception 506 */ 507 private Geometry parseValidArea( Node node ) 508 throws XMLParsingException { 509 510 Geometry geom = null; 511 512 List<Node> nl = XMLTools.getNodes( node, "./deegreewms:ValidArea/*", nsContext ); 513 if ( node != null ) { 514 515 try { 516 for ( int i = 0; i < nl.size(); i++ ) { 517 518 if ( nl.get( 0 ).getNamespaceURI().equals( GMLNS.toString() ) ) { 519 520 geom = GMLGeometryAdapter.wrap( (Element) nl.get( 0 ), null ); 521 break; 522 } 523 } 524 } catch ( GeometryException e ) { 525 e.printStackTrace(); 526 throw new XMLParsingException( "couldn't parse/create valid aera of a datasource", e ); 527 } 528 } 529 530 return geom; 531 } 532 533 /** 534 * @param vendor 535 * @return the parsed list 536 * @throws XMLParsingException 537 */ 538 static List<String> parsePassedParameters( Node vendor ) 539 throws XMLParsingException { 540 List<String> passedParameters = new ArrayList<String>( 10 ); 541 542 if ( vendor == null ) { 543 return passedParameters; 544 } 545 546 List<Node> nl = XMLTools.getNodes( vendor, "deegreewms:PassedVendorspecificParameter/deegreewms:Name", 547 nsContext ); 548 549 for ( Object obj : nl ) { 550 passedParameters.add( ( (Node) obj ).getTextContent().toUpperCase() ); 551 } 552 553 return passedParameters; 554 } 555 556 /** 557 * @param vendor 558 * @return the parsed map 559 * @throws XMLParsingException 560 */ 561 static Map<String, String> parseAddedParameters( Node vendor ) 562 throws XMLParsingException { 563 Map<String, String> addedParameters = new HashMap<String, String>( 10 ); 564 565 if ( vendor == null ) { 566 return addedParameters; 567 } 568 569 List<Node> nl = XMLTools.getNodes( 570 vendor, 571 "deegreewms:AddedVendorspecificParameter/deegreewms:VendorspecificParameter", 572 nsContext ); 573 574 for ( Object obj : nl ) { 575 String pName = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewms:Name", nsContext ); 576 String pValue = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewms:Value", nsContext ); 577 578 addedParameters.put( pName, pValue ); 579 } 580 return addedParameters; 581 } 582 583 /** 584 * @param node 585 * @param failOnEx 586 * @param queryable 587 * @param name 588 * @param geoProp 589 * @param url 590 * @param scaleHint 591 * @throws Exception 592 */ 593 private RemoteWMSDataSource createRemoteWMSDataSource( Node node, boolean failOnEx, boolean queryable, 594 QualifiedName name, URL url, ScaleHint scaleHint, 595 Geometry validArea, int reqTimeLimit ) 596 throws Exception { 597 int type = AbstractDataSource.REMOTEWMS; 598 599 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource"; 600 Node fitNode = XMLTools.getNode( node, s, nsContext ); 601 URL fitURL = null; 602 if ( fitNode != null ) { 603 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref(); 604 } 605 606 GetMap getMap = parseWMSFilterCondition( node ); 607 Color[] colors = parseTransparentColors( node ); 608 WMSCapabilities wCapa = null; 609 if ( capaCache.get( url ) != null ) { 610 wCapa = (WMSCapabilities) capaCache.get( url ); 611 } else { 612 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); 613 LOG.logDebug( "Fetching remote WMS capabilities from URL " + url ); 614 doc.load( url ); 615 LOG.logDebug( "Fetching remote WMS capabilities from URL " + url + " succeeded." ); 616 wCapa = (WMSCapabilities) doc.parseCapabilities(); 617 capaCache.put( url, wCapa ); 618 } 619 OGCWebService ows = new RemoteWMService( wCapa ); 620 621 // parse added/passed parameter map/list 622 Node vendor = XMLTools.getNode( node, 623 "deegreewms:FilterCondition/deegreewms:VendorspecificParameterDefinition", 624 nsContext ); 625 626 List<String> passedParameters = parsePassedParameters( vendor ); 627 Map<String, String> addedParameters = parseAddedParameters( vendor ); 628 629 return new RemoteWMSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getMap, 630 colors, fitURL, reqTimeLimit, passedParameters, addedParameters ); 631 } 632 633 /** 634 * @param node 635 * @param failOnEx 636 * @param queryable 637 * @param name 638 * @param geoProp 639 * @param url 640 * @param scaleHint 641 * @throws Exception 642 */ 643 private RemoteWFSDataSource createRemoteWFSDataSource( Node node, boolean failOnEx, boolean queryable, 644 QualifiedName name, URL url, ScaleHint scaleHint, 645 Geometry validArea, int reqTimeLimit ) 646 throws Exception { 647 int type = AbstractDataSource.REMOTEWFS; 648 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource"; 649 Node fitNode = XMLTools.getNode( node, s, nsContext ); 650 URL fitURL = null; 651 if ( fitNode != null ) { 652 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref(); 653 } 654 Query query = parseWFSFilterCondition( node ); 655 656 WFSCapabilities wfsCapa = null; 657 if ( capaCache.get( url ) != null ) { 658 wfsCapa = (WFSCapabilities) capaCache.get( url ); 659 } else { 660 WFSCapabilitiesDocument wfsDoc = new WFSCapabilitiesDocument(); 661 wfsDoc.load( url ); 662 wfsCapa = (WFSCapabilities) wfsDoc.parseCapabilities(); 663 capaCache.put( url, wfsCapa ); 664 } 665 OGCWebService ows = new RemoteWFService( wfsCapa ); 666 // OGCWebService ows = null; 667 668 Node geoPropNode = XMLTools.getNode( node, "deegreewms:GeometryProperty/text()", nsContext ); 669 QualifiedName geoProp = DEFAULT_GEO_PROP; 670 if ( geoPropNode != null ) { 671 geoProp = parseQualifiedName( geoPropNode ); 672 } 673 674 return new RemoteWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, 675 query, fitURL, reqTimeLimit ); 676 677 } 678 679 /** 680 * @param node 681 * @param failOnEx 682 * @param queryable 683 * @param name 684 * @param geoProp 685 * @param url 686 * @param scaleHint 687 * @throws Exception 688 */ 689 private LocalWCSDataSource createLocalWCSDataSource( Node node, boolean failOnEx, boolean queryable, 690 QualifiedName name, URL url, ScaleHint scaleHint, 691 Geometry validArea, int reqTimeLimit ) 692 throws Exception { 693 int type = AbstractDataSource.LOCALWCS; 694 GetCoverage getCoverage = parseWCSFilterCondition( node ); 695 Color[] colors = parseTransparentColors( node ); 696 WCSConfiguration configuration = null; 697 if ( capaCache.get( url ) != null ) { 698 configuration = (WCSConfiguration) capaCache.get( url ); 699 } else { 700 configuration = WCSConfiguration.create( url ); 701 capaCache.put( url, configuration ); 702 } 703 704 OGCWebService ows = new WCService( configuration ); 705 706 return new LocalWCSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getCoverage, 707 colors, reqTimeLimit ); 708 } 709 710 /** 711 * @param node 712 * @param failOnEx 713 * @param queryable 714 * @param name 715 * @param geoProp 716 * @param url 717 * @param scaleHint 718 * @throws Exception 719 */ 720 private LocalWFSDataSource createLocalWFSDataSource( Node node, boolean failOnEx, boolean queryable, 721 QualifiedName name, URL url, ScaleHint scaleHint, 722 Geometry validArea, int reqTimeLimit ) 723 throws Exception { 724 int type = AbstractDataSource.LOCALWFS; 725 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource"; 726 Node fitNode = XMLTools.getNode( node, s, nsContext ); 727 URL fitURL = null; 728 if ( fitNode != null ) { 729 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref(); 730 } 731 Query query = parseWFSFilterCondition( node ); 732 WFSConfiguration wfsCapa = null; 733 if ( capaCache.get( url ) != null ) { 734 wfsCapa = (WFSConfiguration) capaCache.get( url ); 735 } else { 736 WFSConfigurationDocument wfsDoc = new WFSConfigurationDocument(); 737 wfsDoc.load( url ); 738 wfsCapa = wfsDoc.getConfiguration(); 739 // wfsCapa = new WFSCapabilitiesDocument( url ).createCapabilities(); 740 capaCache.put( url, wfsCapa ); 741 } 742 // OGCWebService ows = WFServiceFactory.getUncachedService( wfsCapa ); 743 OGCWebService ows = WFServiceFactory.createInstance( wfsCapa ); 744 745 Node geoPropNode = XMLTools.getNode( node, "deegreewms:GeometryProperty/text()", nsContext ); 746 QualifiedName geoProp = DEFAULT_GEO_PROP; 747 if ( geoPropNode != null ) { 748 geoProp = parseQualifiedName( geoPropNode ); 749 } 750 751 LOG.logDebug( "geometry property", geoProp ); 752 753 return new LocalWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, query, 754 fitURL, reqTimeLimit ); 755 } 756 757 /** 758 * @param nl 759 * @param type 760 * @throws XMLParsingException 761 */ 762 private Color[] parseTransparentColors( Node node ) 763 throws XMLParsingException { 764 765 String s = "./deegreewms:TransparentColors/deegreewms:Color"; 766 List<Node> clnl = XMLTools.getNodes( node, s, nsContext ); 767 Color[] colors = new Color[clnl.size()]; 768 for ( int j = 0; j < colors.length; j++ ) { 769 colors[j] = Color.decode( XMLTools.getStringValue( clnl.get( j ) ) ); 770 } 771 772 return colors; 773 } 774 775 /** 776 * 777 * @param node 778 * @return the query 779 * @throws XMLParsingException 780 */ 781 private Query parseWFSFilterCondition( Node node ) 782 throws XMLParsingException { 783 784 Query o = null; 785 786 Node queryNode = XMLTools.getNode( node, "./deegreewms:FilterCondition/wfs:Query", nsContext ); 787 if ( queryNode != null ) { 788 try { 789 o = Query.create( (Element) queryNode ); 790 } catch ( Exception e ) { 791 throw new XMLParsingException( StringTools.stackTraceToString( e ) ); 792 } 793 } 794 795 return o; 796 } 797 798 /** 799 * 800 * @param node 801 * @return the request 802 * @throws XMLParsingException 803 */ 804 private GetCoverage parseWCSFilterCondition( Node node ) 805 throws XMLParsingException { 806 807 GetCoverage o = null; 808 809 String id = "" + IDGenerator.getInstance().generateUniqueID(); 810 811 StringBuffer sd = new StringBuffer( 1000 ); 812 sd.append( "version=1.0.0&Coverage=%default%&" ); 813 sd.append( "CRS=EPSG:4326&BBOX=0,0,1,1&Width=1" ); 814 sd.append( "&Height=1&Format=%default%&" ); 815 String s = XMLTools.getNodeAsString( node, "./deegreewms:FilterCondition/deegreewms:WCSRequest", nsContext, "" ); 816 sd.append( s ); 817 try { 818 o = GetCoverage.create( id, sd.toString() ); 819 } catch ( Exception e ) { 820 throw new XMLParsingException( "could not create GetCoverage from layer FilterCondition", e ); 821 } 822 823 return o; 824 } 825 826 /** 827 * 828 * @param node 829 * @return the request 830 * @throws XMLParsingException 831 */ 832 private GetMap parseWMSFilterCondition( Node node ) 833 throws XMLParsingException { 834 835 GetMap o = null; 836 837 String id = "" + IDGenerator.getInstance().generateUniqueID(); 838 839 StringBuffer sd = new StringBuffer( 1000 ); 840 sd.append( "REQUEST=GetMap&LAYERS=%default%&" ); 841 sd.append( "STYLES=&SRS=EPSG:4326&BBOX=0,0,1,1&WIDTH=1&" ); 842 sd.append( "HEIGHT=1&FORMAT=%default%" ); 843 Map<String, String> map1 = KVP2Map.toMap( sd.toString() ); 844 String s = XMLTools.getRequiredNodeAsString( node, "./deegreewms:FilterCondition/deegreewms:WMSRequest", 845 nsContext ); 846 Map<String, String> map2 = KVP2Map.toMap( s ); 847 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) { 848 map2.put( "VERSION", "1.1.1" ); 849 } 850 // if no service is set use WMS as default 851 if ( map2.get( "SERVICE" ) == null ) { 852 map2.put( "SERVICE", "WMS" ); 853 } 854 map1.putAll( map2 ); 855 try { 856 map1.put( "ID", id ); 857 o = GetMap.create( map1 ); 858 } catch ( Exception e ) { 859 throw new XMLParsingException( "could not create GetMap from layer FilterCondition", e ); 860 } 861 862 return o; 863 } 864 865 /** 866 * 867 * @param layerElem 868 * @throws XMLParsingException 869 */ 870 @Override 871 protected Style[] parseStyles( Element layerElem ) 872 throws XMLParsingException { 873 874 List<Node> nl = XMLTools.getNodes( layerElem, "./Style", nsContext ); 875 Style[] styles = new Style[nl.size()]; 876 for ( int i = 0; i < styles.length; i++ ) { 877 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Name", nsContext ); 878 String title = XMLTools.getNodeAsString( nl.get( i ), "./Title", nsContext, null ); 879 String styleAbstract = XMLTools.getNodeAsString( nl.get( i ), "./Abstract", nsContext, null ); 880 LegendURL[] legendURLs = parseLegendURL( nl.get( i ) ); 881 StyleURL styleURL = parseStyleURL( nl.get( i ) ); 882 StyleSheetURL styleSheetURL = parseStyleSheetURL( nl.get( i ) ); 883 String styleResource = XMLTools.getNodeAsString( nl.get( i ), "deegreewms:StyleResource", nsContext, 884 "styles.xml" ); 885 URL sr = null; 886 try { 887 sr = resolve( styleResource ); 888 } catch ( MalformedURLException e ) { 889 throw new XMLParsingException( "could not parse style resource of style: " + name, e ); 890 } 891 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, sr ); 892 } 893 894 return styles; 895 } 896 897 }