001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wms/GetMapServiceInvoker.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;
037
038 import java.io.IOException;
039 import java.net.MalformedURLException;
040 import java.net.URI;
041 import java.net.URL;
042 import java.util.ArrayList;
043 import java.util.HashMap;
044 import java.util.List;
045 import java.util.Map;
046
047 import org.deegree.datatypes.QualifiedName;
048 import org.deegree.framework.log.ILogger;
049 import org.deegree.framework.log.LoggerFactory;
050 import org.deegree.framework.xml.NamespaceContext;
051 import org.deegree.framework.xml.XMLParsingException;
052 import org.deegree.framework.xml.schema.XMLSchemaException;
053 import org.deegree.graphics.sld.AbstractLayer;
054 import org.deegree.graphics.sld.FeatureTypeConstraint;
055 import org.deegree.graphics.sld.LayerFeatureConstraints;
056 import org.deegree.graphics.sld.UserLayer;
057 import org.deegree.i18n.Messages;
058 import org.deegree.model.crs.UnknownCRSException;
059 import org.deegree.model.feature.schema.FeatureType;
060 import org.deegree.model.feature.schema.GMLSchema;
061 import org.deegree.model.feature.schema.GMLSchemaDocument;
062 import org.deegree.model.feature.schema.GeometryPropertyType;
063 import org.deegree.ogcbase.ElementStep;
064 import org.deegree.ogcbase.PropertyPath;
065 import org.deegree.ogcbase.PropertyPathStep;
066 import org.deegree.ogcwebservices.InconsistentRequestException;
067 import org.deegree.ogcwebservices.InvalidParameterValueException;
068 import org.deegree.ogcwebservices.OGCWebService;
069 import org.deegree.ogcwebservices.OGCWebServiceException;
070 import org.deegree.ogcwebservices.OWSUtils;
071 import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType;
072 import org.deegree.ogcwebservices.wfs.operation.FeatureTypeDescription;
073 import org.deegree.ogcwebservices.wms.capabilities.Layer;
074 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
075 import org.xml.sax.SAXException;
076
077 /**
078 *
079 *
080 *
081 * @version $Revision: 18195 $
082 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
083 * @author last edited by: $Author: mschneider $
084 *
085 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
086 *
087 * @since 2.0
088 */
089 public abstract class GetMapServiceInvoker {
090
091 private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvoker.class );
092
093 private static Map<QualifiedName, List<PropertyPath>> geoProps;
094
095 static {
096 if ( geoProps == null ) {
097 geoProps = new HashMap<QualifiedName, List<PropertyPath>>();
098 }
099 }
100
101 /**
102 * default get map handler
103 */
104 protected final DefaultGetMapHandler handler;
105
106 /**
107 * scale denominator
108 */
109 protected double scaleDen = 0;
110
111 /**
112 *
113 * @param handler
114 * @param scaleDen
115 */
116 public GetMapServiceInvoker( DefaultGetMapHandler handler, double scaleDen ) {
117 this.handler = handler;
118 this.scaleDen = scaleDen;
119 }
120
121 /**
122 * the method accesses the GML schema of the feature types being part of the passed FeatureTypeConstraints and
123 * extracts the geometry property definition. The names of the geometry properties will be added as PropertyPath's
124 * to passed list
125 *
126 * @param layer
127 * @param ftc
128 * @param pp
129 * @return the list of property paths
130 * @throws OGCWebServiceException
131 * @throws SAXException
132 * @throws IOException
133 * @throws XMLParsingException
134 * @throws XMLSchemaException
135 * @throws UnknownCRSException
136 */
137 protected List<PropertyPath> findGeoProperties( AbstractLayer layer, FeatureTypeConstraint[] ftc,
138 List<PropertyPath> pp )
139 throws OGCWebServiceException, IOException, SAXException, XMLSchemaException,
140 XMLParsingException, UnknownCRSException {
141
142 GMLSchemaDocument doc = null;
143 for ( int i = 0; i < ftc.length; i++ ) {
144 if ( geoProps.get( ftc[i].getFeatureTypeName() ) == null ) {
145 if ( layer instanceof UserLayer && ( (UserLayer) layer ).getRemoteOWS() != null ) {
146 doc = getSchemaFromRemoteWFS( (UserLayer) layer, ftc[i] );
147 } else {
148 doc = getSchemaFromLocalWFS( layer, ftc[i] );
149 }
150 GMLSchema schema = doc.parseGMLSchema();
151 FeatureType ft = schema.getFeatureType( ftc[i].getFeatureTypeName() );
152 if ( ft == null ) {
153 throw new OGCWebServiceException( Messages.get( "WFS_FEATURE_TYPE_UNKNOWN",
154 ftc[i].getFeatureTypeName() ) );
155 }
156 GeometryPropertyType[] gpt = ft.getGeometryProperties();
157
158 List<PropertyPath> tmp = new ArrayList<PropertyPath>( gpt.length );
159 for ( int j = 0; j < gpt.length; j++ ) {
160 try {
161 String pre = ftc[i].getFeatureTypeName().getPrefix();
162 QualifiedName qn = new QualifiedName( pre, gpt[j].getName().getLocalName(),
163 gpt[j].getName().getNamespace() );
164 PropertyPathStep step = new ElementStep( qn );
165 List<PropertyPathStep> steps = new ArrayList<PropertyPathStep>();
166 steps.add( step );
167 PropertyPath prop = new PropertyPath( steps );
168 pp.add( prop );
169 tmp.add( prop );
170 } catch ( Exception e ) {
171 e.printStackTrace();
172 }
173 }
174 geoProps.put( ftc[i].getFeatureTypeName(), tmp );
175 } else {
176 List<PropertyPath> tmp = geoProps.get( ftc[i].getFeatureTypeName() );
177 pp.addAll( tmp );
178 }
179
180 }
181
182 return pp;
183 }
184
185 /**
186 * accesses the GML schema assigned to the feature type contained within the passed FeatureTypeConstraint from a
187 * remote WFS by performing a DescribeFeatureType request
188 *
189 * @param layer
190 * @param ftc
191 * @return the schema document
192 * @throws InconsistentRequestException
193 * @throws InvalidParameterValueException
194 * @throws OGCWebServiceException
195 */
196 private GMLSchemaDocument getSchemaFromLocalWFS( AbstractLayer layer, FeatureTypeConstraint ftc )
197 throws InconsistentRequestException, InvalidParameterValueException, OGCWebServiceException {
198 StringBuffer sb = new StringBuffer( 300 );
199 sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
200 QualifiedName qn = ftc.getFeatureTypeName();
201 sb.append( qn.getPrefixedName() );
202 sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
203 sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
204 LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
205 DescribeFeatureType dft = DescribeFeatureType.create( "rt", sb.toString() );
206 OGCWebService wfs = getResponsibleService( layer );
207 FeatureTypeDescription ftd = (FeatureTypeDescription) wfs.doService( dft );
208 GMLSchemaDocument doc = new GMLSchemaDocument();
209 doc.setRootElement( ftd.getFeatureTypeSchema().getRootElement() );
210 return doc;
211 }
212
213 /**
214 * accesses the GML schema assigned to the feature type contained within the passed FeatureTypeConstraint from a
215 * local WFS by performing a DescribeFeatureType request
216 *
217 * @param ftc
218 * @return the schema document
219 * @throws IOException
220 * @throws SAXException
221 * @throws MalformedURLException
222 */
223 private GMLSchemaDocument getSchemaFromRemoteWFS( UserLayer layer, FeatureTypeConstraint ftc )
224 throws IOException, SAXException, MalformedURLException {
225 URL url = layer.getRemoteOWS().getOnlineResource();
226 StringBuffer sb = new StringBuffer( 300 );
227 sb.append( OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) );
228 sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
229 QualifiedName qn = ftc.getFeatureTypeName();
230 sb.append( qn.getPrefixedName() );
231 sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
232 sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
233 LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
234 GMLSchemaDocument doc = new GMLSchemaDocument();
235 doc.load( new URL( sb.toString() ) );
236 return doc;
237 }
238
239 /**
240 * @param layer
241 * @return the service instance
242 * @throws OGCWebServiceException
243 * if no service could be found
244 */
245 protected OGCWebService getResponsibleService( AbstractLayer layer )
246 throws OGCWebServiceException {
247
248 LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints();
249 FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
250 Layer root = handler.getConfiguration().getLayer();
251 OGCWebService wfs = findService( root, ftc[0].getFeatureTypeName() );
252 if ( wfs == null ) {
253 throw new OGCWebServiceException( this.getClass().getName(), "feature type: " + ftc[0].getFeatureTypeName()
254 + " is not served by this WMS/WFS" );
255 }
256
257 return wfs;
258 }
259
260 /**
261 * searches/findes the WFService that is resposible for handling the feature types of the current request. If no
262 * WFService instance can be found <code>null</code> will be returned to indicated that the current feature type is
263 * not served by the internal WFS of a WMS
264 *
265 * @param layer
266 * @param featureType
267 * @return the service instance or null
268 * @throws OGCWebServiceException
269 */
270 private OGCWebService findService( Layer layer, QualifiedName featureType )
271 throws OGCWebServiceException {
272 Layer[] layers = layer.getLayer();
273 for ( int i = 0; i < layers.length; i++ ) {
274 AbstractDataSource[] ad = layers[i].getDataSource();
275 if ( ad != null ) {
276 for ( int j = 0; j < ad.length; j++ ) {
277 if ( ad[j].getName().equals( featureType ) ) {
278
279 return ad[j].getOGCWebService();
280 }
281 }
282 }
283 // recursion
284 OGCWebService wfs = findService( layers[i], featureType );
285 if ( wfs != null ) {
286 return wfs;
287 }
288 }
289
290 return null;
291 }
292
293 /**
294 * extracts all used namespace definitions from a set of PropertyPath's
295 *
296 * @param pp
297 * @return the used namespace definitions from a set of PropertyPath's
298 */
299 protected Map<String, URI> extractNameSpaceDef( List<PropertyPath> pp ) {
300 Map<String, URI> map = new HashMap<String, URI>();
301 for ( int i = 0; i < pp.size(); i++ ) {
302 NamespaceContext nsc = pp.get( i ).getNamespaceContext();
303 map.putAll( nsc.getNamespaceMap() );
304 }
305 return map;
306 }
307
308 }