001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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: 21877 $ 082 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 083 * @author last edited by: $Author: aschmitz $ 084 * 085 * @version 1.0. $Revision: 21877 $, $Date: 2010-01-12 09:03:37 +0100 (Di, 12 Jan 2010) $ 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 if ( qn.getNamespace() != null ) { 232 sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' ); 233 sb.append( qn.getNamespace().toASCIIString() ).append( ')' ); 234 } 235 LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb ); 236 GMLSchemaDocument doc = new GMLSchemaDocument(); 237 doc.load( new URL( sb.toString() ) ); 238 return doc; 239 } 240 241 /** 242 * @param layer 243 * @return the service instance 244 * @throws OGCWebServiceException 245 * if no service could be found 246 */ 247 protected OGCWebService getResponsibleService( AbstractLayer layer ) 248 throws OGCWebServiceException { 249 250 LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints(); 251 FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint(); 252 Layer root = handler.getConfiguration().getLayer(); 253 OGCWebService wfs = findService( root, ftc[0].getFeatureTypeName() ); 254 if ( wfs == null ) { 255 throw new OGCWebServiceException( this.getClass().getName(), "feature type: " + ftc[0].getFeatureTypeName() 256 + " is not served by this WMS/WFS" ); 257 } 258 259 return wfs; 260 } 261 262 /** 263 * searches/findes the WFService that is resposible for handling the feature types of the current request. If no 264 * WFService instance can be found <code>null</code> will be returned to indicated that the current feature type is 265 * not served by the internal WFS of a WMS 266 * 267 * @param layer 268 * @param featureType 269 * @return the service instance or null 270 * @throws OGCWebServiceException 271 */ 272 private OGCWebService findService( Layer layer, QualifiedName featureType ) 273 throws OGCWebServiceException { 274 Layer[] layers = layer.getLayer(); 275 for ( int i = 0; i < layers.length; i++ ) { 276 AbstractDataSource[] ad = layers[i].getDataSource(); 277 if ( ad != null ) { 278 for ( int j = 0; j < ad.length; j++ ) { 279 if ( ad[j].getName().equals( featureType ) ) { 280 281 return ad[j].getOGCWebService(); 282 } 283 } 284 } 285 // recursion 286 OGCWebService wfs = findService( layers[i], featureType ); 287 if ( wfs != null ) { 288 return wfs; 289 } 290 } 291 292 return null; 293 } 294 295 /** 296 * extracts all used namespace definitions from a set of PropertyPath's 297 * 298 * @param pp 299 * @return the used namespace definitions from a set of PropertyPath's 300 */ 301 protected Map<String, URI> extractNameSpaceDef( List<PropertyPath> pp ) { 302 Map<String, URI> map = new HashMap<String, URI>(); 303 for ( int i = 0; i < pp.size(); i++ ) { 304 NamespaceContext nsc = pp.get( i ).getNamespaceContext(); 305 map.putAll( nsc.getNamespaceMap() ); 306 } 307 return map; 308 } 309 310 }