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