001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wfs/RemoteWFService.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.wfs; 037 038 import java.io.InputStreamReader; 039 import java.io.StringReader; 040 import java.io.StringWriter; 041 import java.net.URL; 042 import java.util.HashMap; 043 import java.util.Map; 044 045 import org.deegree.framework.log.ILogger; 046 import org.deegree.framework.log.LoggerFactory; 047 import org.deegree.framework.util.CharsetUtils; 048 import org.deegree.framework.util.MimeTypeMapper; 049 import org.deegree.framework.util.NetWorker; 050 import org.deegree.framework.util.StringTools; 051 import org.deegree.framework.xml.XMLFragment; 052 import org.deegree.model.feature.FeatureCollection; 053 import org.deegree.model.feature.GMLFeatureCollectionDocument; 054 import org.deegree.ogcwebservices.OGCWebService; 055 import org.deegree.ogcwebservices.OGCWebServiceException; 056 import org.deegree.ogcwebservices.OGCWebServiceRequest; 057 import org.deegree.ogcwebservices.OWSUtils; 058 import org.deegree.ogcwebservices.getcapabilities.DCPType; 059 import org.deegree.ogcwebservices.getcapabilities.HTTP; 060 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 061 import org.deegree.ogcwebservices.getcapabilities.Operation; 062 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 063 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument_1_0_0; 064 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument_1_1_0; 065 import org.deegree.ogcwebservices.wfs.capabilities.WFSOperationsMetadata; 066 import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType; 067 import org.deegree.ogcwebservices.wfs.operation.FeatureResult; 068 import org.deegree.ogcwebservices.wfs.operation.FeatureTypeDescription; 069 import org.deegree.ogcwebservices.wfs.operation.GetFeature; 070 import org.deegree.ogcwebservices.wfs.operation.LockFeature; 071 import org.deegree.ogcwebservices.wfs.operation.WFSGetCapabilities; 072 import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction; 073 074 /** 075 * An instance of the class acts as a wrapper to a remote WFS. 076 * 077 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 078 * @author last edited by: $Author: mschneider $ 079 * 080 * @version $Revision: 18195 $ 081 */ 082 public class RemoteWFService implements OGCWebService { 083 084 private static final ILogger LOG = LoggerFactory.getLogger( RemoteWFService.class ); 085 086 protected static final String GETCAPABILITIES = "GETCAPABILITIES"; 087 088 protected static final String GETFEATURE = "GETFEATURE"; 089 090 protected static final String GETFEATUREWITHLOCK = "GETFEATUREWITHLOCK"; 091 092 protected static final String DESCRIBEFEATURETYPE = "DESCRIBEFEATURETYPE"; 093 094 protected static final String TRANSACTION = "TRANSACTION"; 095 096 protected static final String LOCKFEATURE = "LOCKFEATURE"; 097 098 protected WFSCapabilities capabilities = null; 099 100 protected Map<String, URL> addresses = new HashMap<String, URL>(); 101 102 /** 103 * Creates a new instance of RemoteWFService 104 * 105 * @param capabilities 106 * @throws OGCWebServiceException 107 */ 108 public RemoteWFService( WFSCapabilities capabilities ) throws OGCWebServiceException { 109 110 this.capabilities = capabilities; 111 112 WFSOperationsMetadata om = (WFSOperationsMetadata) capabilities.getOperationsMetadata(); 113 Operation op = om.getGetCapabilitiesOperation(); 114 115 // get GetCapabilities address 116 DCPType[] dcp = op.getDCPs(); 117 URL[] get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 118 addresses.put( GETCAPABILITIES, get[0] ); 119 120 // get GetFeature address 121 op = om.getGetFeature(); 122 dcp = op.getDCPs(); 123 boolean po = false; 124 for ( int i = 0; i < dcp.length; i++ ) { 125 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 126 if ( get != null && get.length > 0 ) { 127 addresses.put( GETFEATURE, get[0] ); 128 po = true; 129 } 130 } 131 if ( !po ) { 132 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() + " doesn't " 133 + "support HTTP POST for GetFeature requests"; 134 LOG.logDebug( s ); 135 throw new OGCWebServiceException( s ); 136 } 137 138 // get DescribeFeatureType address 139 op = om.getDescribeFeatureType(); 140 dcp = op.getDCPs(); 141 get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 142 addresses.put( DESCRIBEFEATURETYPE, get[0] ); 143 144 op = om.getGetFeatureWithLock(); 145 if ( op != null ) { 146 // get GetFeatureWithLock address 147 dcp = op.getDCPs(); 148 po = false; 149 for ( int i = 0; i < dcp.length; i++ ) { 150 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 151 if ( get != null && get.length > 0 ) { 152 addresses.put( GETFEATUREWITHLOCK, get[0] ); 153 po = true; 154 } 155 } 156 if ( !po ) { 157 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() 158 + " doesn't support HTTP POST for GetFeatureWithLock requests"; 159 LOG.logDebug( s ); 160 throw new OGCWebServiceException( s ); 161 } 162 } 163 164 op = om.getTransaction(); 165 if ( op != null ) { 166 // get Transaction address 167 dcp = op.getDCPs(); 168 po = false; 169 for ( int i = 0; i < dcp.length; i++ ) { 170 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 171 if ( get != null && get.length > 0 ) { 172 addresses.put( TRANSACTION, get[0] ); 173 po = true; 174 } 175 } 176 if ( !po ) { 177 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() 178 + " doesn't support HTTP POST for Transaction requests"; 179 LOG.logDebug( s ); 180 throw new OGCWebServiceException( s ); 181 } 182 } 183 184 op = om.getLockFeature(); 185 if ( op != null ) { 186 // get LockFeature address 187 dcp = op.getDCPs(); 188 get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 189 if ( get != null && get.length > 0 ) { 190 addresses.put( LOCKFEATURE, get[0] ); 191 } 192 } 193 194 } 195 196 /** 197 * 198 * @return capabilities 199 */ 200 public WFSCapabilities getWFSCapabilities() { 201 return capabilities; 202 } 203 204 /* 205 * (non-Javadoc) 206 * 207 * @see org.deegree.ogcwebservices.OGCWebService#doService(org.deegree.ogcwebservices.OGCWebServiceRequest) 208 */ 209 public Object doService( OGCWebServiceRequest request ) 210 throws OGCWebServiceException { 211 Object response = null; 212 if ( request instanceof GetFeature ) { 213 response = handleGetFeature( (GetFeature) request ); 214 } else if ( request instanceof DescribeFeatureType ) { 215 response = handleDescribeFeatureType( (DescribeFeatureType) request ); 216 } else if ( request instanceof WFSGetCapabilities ) { 217 response = handleGetCapabilities( (WFSGetCapabilities) request ); 218 } else if ( request instanceof LockFeature ) { 219 response = handleLockFeature( (LockFeature) request ); 220 } else if ( request instanceof Transaction ) { 221 response = handleTransaction( (Transaction) request ); 222 } 223 return response; 224 } 225 226 /** 227 * performs a GetFeature request against the remote service. The method uses http-POST to call the remote WFS 228 * 229 * @param request 230 * get feature request 231 */ 232 private FeatureResult handleGetFeature( GetFeature request ) 233 throws OGCWebServiceException { 234 235 URL url = addresses.get( GETFEATURE ); 236 StringWriter writer = new StringWriter( 1000 ); 237 try { 238 if ( "1.0.0".equals( capabilities.getVersion() ) ) { 239 XMLFactory_1_0_0.export( request ).write( writer ); 240 } else { 241 XMLFactory.export( request ).write( writer ); 242 } 243 } catch ( Exception e ) { 244 LOG.logError( e.getMessage(), e ); 245 throw new OGCWebServiceException( "could not transform GetFeature requst to its string representation" ); 246 } 247 String param = writer.getBuffer().toString(); 248 249 FeatureCollection result = null; 250 try { 251 // get map from the remote service 252 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url, param ); 253 String contentType = nw.getContentType(); 254 if ( contentType == null || MimeTypeMapper.isKnownMimeType( contentType ) ) { 255 try { 256 InputStreamReader isr = new InputStreamReader( nw.getInputStream(), CharsetUtils.getSystemCharset() ); 257 GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument(); 258 doc.load( isr, url.toString() ); 259 result = doc.parse(); 260 } catch ( Exception e ) { 261 throw new OGCWebServiceException( e.toString() ); 262 } 263 } else { 264 String msg = StringTools.concat( 500, "Response of the remote WFS contains unknown content type: ", 265 contentType, ";request: ", param ); 266 throw new OGCWebServiceException( "RemoteWFS:handleGetFeature", msg ); 267 } 268 } catch ( Exception e ) { 269 LOG.logError( e.getMessage(), e ); 270 String msg = StringTools.concat( 500, "Could not get feature from RemoteWFS: ", 271 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 272 ';' ); 273 throw new OGCWebServiceException( "RemoteWFS:handleGetFeature", msg ); 274 275 } 276 277 FeatureResult fr = new FeatureResult( request, result ); 278 return fr; 279 280 } 281 282 /** 283 * Performs a describe feature type request against a remote WFS. The method uses http-GET to call the remote WFS 284 * 285 * @param request 286 * describe feature type request 287 */ 288 private FeatureTypeDescription handleDescribeFeatureType( DescribeFeatureType request ) 289 throws OGCWebServiceException { 290 291 URL url = addresses.get( DESCRIBEFEATURETYPE ); 292 293 String param = request.getRequestParameter(); 294 295 String result = null; 296 try { 297 String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param; 298 URL ur = new URL( us ); 299 // get map from the remote service 300 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), ur ); 301 byte[] b = nw.getDataAsByteArr( 20000 ); 302 String contentType = nw.getContentType(); 303 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 304 // create a WFSCapabilities instance from the result 305 result = new String( b ); 306 } else { 307 String msg = StringTools.concat( 500, "Response of the remote WFS contains unknown content type: ", 308 contentType, ";request: ", param ); 309 throw new OGCWebServiceException( "RemoteWFS:handleDescribeFeatureType", msg ); 310 } 311 } catch ( Exception e ) { 312 LOG.logError( e.getMessage(), e ); 313 String msg = StringTools.concat( 500, "Could not get map from RemoteWFS: ", 314 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 315 ';' ); 316 throw new OGCWebServiceException( "RemoteWFS:handleDescribeFeatureType", msg ); 317 318 } 319 320 FeatureTypeDescription ftd = null; 321 try { 322 XMLFragment frag = new XMLFragment( new StringReader( result ), XMLFragment.DEFAULT_URL ); 323 ftd = new FeatureTypeDescription( frag ); 324 } catch ( Exception e1 ) { 325 LOG.logError( e1.getMessage(), e1 ); 326 throw new OGCWebServiceException( this.getClass().getName() + "Could not create response", 327 StringTools.stackTraceToString( e1 ) ); 328 } 329 330 return ftd; 331 } 332 333 private String toKVPRequest() { 334 return null; 335 } 336 337 /** 338 * reads the capabilities from the remote WFS by performing a GetCapabilities request against it. The method uses 339 * http-GET to call the remote WFS 340 * 341 * @param request 342 * capabilities request 343 */ 344 private WFSCapabilities handleGetCapabilities( WFSGetCapabilities request ) 345 throws OGCWebServiceException { 346 347 URL url = addresses.get( GETCAPABILITIES ); 348 String param = request.getRequestParameter(); 349 350 WFSCapabilities response = null; 351 try { 352 String remoteAddress = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ); 353 URL ur = new URL( remoteAddress + param ); 354 XMLFragment responseDoc = new XMLFragment( ur ); 355 String version = responseDoc.getRootElement().getAttribute( "version" ); 356 if ( version == null ) { 357 String msg = "Cannot determine remote WFS version. No 'version' attribute."; 358 throw new OGCWebServiceException( "RemoteWFS:handleGetCapabilities", msg ); 359 } 360 if ( "1.0.0".equals( version ) ) { 361 WFSCapabilitiesDocument_1_0_0 capabilitiesDoc = new WFSCapabilitiesDocument_1_0_0(); 362 capabilitiesDoc.setRootElement( responseDoc.getRootElement() ); 363 response = (WFSCapabilities) capabilitiesDoc.parseCapabilities(); 364 } else if ( "1.1.0".equals( version ) ) { 365 WFSCapabilitiesDocument_1_1_0 capabilitiesDoc = new WFSCapabilitiesDocument_1_1_0(); 366 capabilitiesDoc.setRootElement( responseDoc.getRootElement() ); 367 response = (WFSCapabilities) capabilitiesDoc.parseCapabilities(); 368 } else { 369 String msg = "Cannot communicate with remote WFS. Protocol version '" + version 370 + "' is not supported by RemoteWFService class."; 371 throw new OGCWebServiceException( "RemoteWFS:handleGetCapabilities", msg ); 372 } 373 374 } catch ( Exception e ) { 375 LOG.logError( e.getMessage(), e ); 376 String msg = StringTools.concat( 500, "Could not get map from RemoteWFS: ", 377 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 378 ';' ); 379 throw new OGCWebServiceException( "RemoteWFS:handleGetCapabilities", msg ); 380 381 } 382 return response; 383 384 } 385 386 /** 387 * @param request 388 */ 389 private Object handleLockFeature( LockFeature request ) { 390 // FIXME 391 // TODO 392 return null; 393 } 394 395 /** 396 * @param request 397 */ 398 private Object handleTransaction( Transaction request ) { 399 // FIXME 400 // TODO 401 return null; 402 } 403 404 /* 405 * (non-Javadoc) 406 * 407 * @see org.deegree.ogcwebservices.OGCWebService#getCapabilities() 408 */ 409 public OGCCapabilities getCapabilities() { 410 return capabilities; 411 } 412 413 }