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