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 }