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