001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wfs/RemoteWFService.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstraße 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.ogcwebservices.wfs; 044 045 import java.io.InputStreamReader; 046 import java.io.StringReader; 047 import java.io.StringWriter; 048 import java.net.URL; 049 import java.util.HashMap; 050 import java.util.Map; 051 052 import org.deegree.framework.log.ILogger; 053 import org.deegree.framework.log.LoggerFactory; 054 import org.deegree.framework.util.CharsetUtils; 055 import org.deegree.framework.util.MimeTypeMapper; 056 import org.deegree.framework.util.NetWorker; 057 import org.deegree.framework.util.StringTools; 058 import org.deegree.framework.xml.XMLFragment; 059 import org.deegree.model.feature.FeatureCollection; 060 import org.deegree.model.feature.GMLFeatureCollectionDocument; 061 import org.deegree.ogcwebservices.OGCWebService; 062 import org.deegree.ogcwebservices.OGCWebServiceException; 063 import org.deegree.ogcwebservices.OGCWebServiceRequest; 064 import org.deegree.ogcwebservices.OWSUtils; 065 import org.deegree.ogcwebservices.getcapabilities.DCPType; 066 import org.deegree.ogcwebservices.getcapabilities.HTTP; 067 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 068 import org.deegree.ogcwebservices.getcapabilities.Operation; 069 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 070 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 071 import org.deegree.ogcwebservices.wfs.capabilities.WFSOperationsMetadata; 072 import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType; 073 import org.deegree.ogcwebservices.wfs.operation.FeatureResult; 074 import org.deegree.ogcwebservices.wfs.operation.FeatureTypeDescription; 075 import org.deegree.ogcwebservices.wfs.operation.GetFeature; 076 import org.deegree.ogcwebservices.wfs.operation.LockFeature; 077 import org.deegree.ogcwebservices.wfs.operation.WFSGetCapabilities; 078 import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction; 079 080 /** 081 * An instance of the class acts as a wrapper to a remote WFS. 082 * 083 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 084 * @author last edited by: $Author: apoth $ 085 * 086 * @version $Revision: 9345 $ 087 */ 088 public class RemoteWFService implements OGCWebService { 089 090 private static final ILogger LOG = LoggerFactory.getLogger( RemoteWFService.class ); 091 092 protected static final String GETCAPABILITIES = "GETCAPABILITIES"; 093 094 protected static final String GETFEATURE = "GETFEATURE"; 095 096 protected static final String GETFEATUREWITHLOCK = "GETFEATUREWITHLOCK"; 097 098 protected static final String DESCRIBEFEATURETYPE = "DESCRIBEFEATURETYPE"; 099 100 protected static final String TRANSACTION = "TRANSACTION"; 101 102 protected static final String LOCKFEATURE = "LOCKFEATURE"; 103 104 protected WFSCapabilities capabilities = null; 105 106 protected Map<String, URL> addresses = new HashMap<String, URL>(); 107 108 /** 109 * Creates a new instance of RemoteWFService 110 * 111 * @param capabilities 112 * @throws OGCWebServiceException 113 */ 114 public RemoteWFService( WFSCapabilities capabilities ) throws OGCWebServiceException { 115 116 this.capabilities = capabilities; 117 118 WFSOperationsMetadata om = (WFSOperationsMetadata) capabilities.getOperationsMetadata(); 119 Operation op = om.getGetCapabilitiesOperation(); 120 121 // get GetCapabilities address 122 DCPType[] dcp = op.getDCPs(); 123 URL[] get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 124 addresses.put( GETCAPABILITIES, get[0] ); 125 126 // get GetFeature address 127 op = om.getGetFeature(); 128 dcp = op.getDCPs(); 129 boolean po = false; 130 for ( int i = 0; i < dcp.length; i++ ) { 131 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 132 if ( get != null && get.length > 0 ) { 133 addresses.put( GETFEATURE, get[0] ); 134 po = true; 135 } 136 } 137 if ( !po ) { 138 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() + " doesn't " 139 + "support HTTP POST for GetFeature requests"; 140 LOG.logDebug( s ); 141 throw new OGCWebServiceException( s ); 142 } 143 144 // get DescribeFeatureType address 145 op = om.getDescribeFeatureType(); 146 dcp = op.getDCPs(); 147 get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 148 addresses.put( DESCRIBEFEATURETYPE, get[0] ); 149 150 op = om.getGetFeatureWithLock(); 151 if ( op != null ) { 152 // get GetFeatureWithLock address 153 dcp = op.getDCPs(); 154 po = false; 155 for ( int i = 0; i < dcp.length; i++ ) { 156 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 157 if ( get != null && get.length > 0 ) { 158 addresses.put( GETFEATUREWITHLOCK, get[0] ); 159 po = true; 160 } 161 } 162 if ( !po ) { 163 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() 164 + " doesn't support HTTP POST for GetFeatureWithLock requests"; 165 LOG.logDebug( s ); 166 throw new OGCWebServiceException( s ); 167 } 168 } 169 170 op = om.getTransaction(); 171 if ( op != null ) { 172 // get Transaction address 173 dcp = op.getDCPs(); 174 po = false; 175 for ( int i = 0; i < dcp.length; i++ ) { 176 get = ( (HTTP) dcp[i].getProtocol() ).getPostOnlineResources(); 177 if ( get != null && get.length > 0 ) { 178 addresses.put( TRANSACTION, get[0] ); 179 po = true; 180 } 181 } 182 if ( !po ) { 183 String s = "WFS: " + capabilities.getServiceIdentification().getTitle() 184 + " doesn't support HTTP POST for Transaction requests"; 185 LOG.logDebug( s ); 186 throw new OGCWebServiceException( s ); 187 } 188 } 189 190 op = om.getLockFeature(); 191 if ( op != null ) { 192 // get LockFeature address 193 dcp = op.getDCPs(); 194 get = ( (HTTP) dcp[0].getProtocol() ).getGetOnlineResources(); 195 if ( get != null && get.length > 0 ) { 196 addresses.put( LOCKFEATURE, get[0] ); 197 } 198 } 199 200 } 201 202 /** 203 * 204 * @return capabilities 205 */ 206 public WFSCapabilities getWFSCapabilities() { 207 return capabilities; 208 } 209 210 /* 211 * (non-Javadoc) 212 * 213 * @see org.deegree.ogcwebservices.OGCWebService#doService(org.deegree.ogcwebservices.OGCWebServiceRequest) 214 */ 215 public Object doService( OGCWebServiceRequest request ) 216 throws OGCWebServiceException { 217 Object response = null; 218 if ( request instanceof GetFeature ) { 219 response = handleGetFeature( (GetFeature) request ); 220 } else if ( request instanceof DescribeFeatureType ) { 221 response = handleDescribeFeatureType( (DescribeFeatureType) request ); 222 } else if ( request instanceof WFSGetCapabilities ) { 223 response = handleGetCapabilities( (WFSGetCapabilities) request ); 224 } else if ( request instanceof LockFeature ) { 225 response = handleLockFeature( (LockFeature) request ); 226 } else if ( request instanceof Transaction ) { 227 response = handleTransaction( (Transaction) request ); 228 } 229 return response; 230 } 231 232 /** 233 * performs a GetFeature request against the remote service. The method uses http-POST to call 234 * the remote WFS 235 * 236 * @param request 237 * get feature request 238 */ 239 private FeatureResult handleGetFeature( GetFeature request ) 240 throws OGCWebServiceException { 241 242 URL url = addresses.get( GETFEATURE ); 243 StringWriter writer = new StringWriter( 1000 ); 244 try { 245 XMLFactory.export( request ).write( writer ); 246 } catch ( Exception e ) { 247 LOG.logError( e.getMessage(), e ); 248 throw new OGCWebServiceException( "could not transform GetFeature requst to its string representation" ); 249 } 250 String param = writer.getBuffer().toString(); 251 252 FeatureCollection result = null; 253 try { 254 // get map from the remote service 255 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url, param ); 256 String contentType = nw.getContentType(); 257 if ( contentType == null || MimeTypeMapper.isKnownMimeType( contentType ) ) { 258 try { 259 InputStreamReader isr = new InputStreamReader( nw.getInputStream(), CharsetUtils.getSystemCharset() ); 260 GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument(); 261 doc.load( isr, url.toString() ); 262 result = doc.parse(); 263 } catch ( Exception e ) { 264 throw new OGCWebServiceException( e.toString() ); 265 } 266 } else { 267 String msg = StringTools.concat( 500, "Response of the remote WFS contains unknown content type: ", 268 contentType, ";request: ", param ); 269 throw new OGCWebServiceException( "RemoteWFS:handleGetFeature", msg ); 270 } 271 } catch ( Exception e ) { 272 LOG.logError( e.getMessage(), e ); 273 String msg = StringTools.concat( 500, "Could not get feature from RemoteWFS: ", 274 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 275 ';' ); 276 throw new OGCWebServiceException( "RemoteWFS:handleGetFeature", msg ); 277 278 } 279 280 FeatureResult fr = new FeatureResult( request, result ); 281 282 return fr; 283 284 } 285 286 /** 287 * Pefroms a describe feature type request against a remote WFS. The method uses http-GET to 288 * call the remote WFS 289 * 290 * @param request 291 * describe feature type request 292 * @param client 293 * receiver of the response to the request 294 */ 295 private FeatureTypeDescription handleDescribeFeatureType( DescribeFeatureType request ) 296 throws OGCWebServiceException { 297 298 URL url = addresses.get( DESCRIBEFEATURETYPE ); 299 300 String param = request.getRequestParameter(); 301 302 String result = null; 303 try { 304 String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param; 305 URL ur = new URL( us ); 306 // get map from the remote service 307 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), ur ); 308 byte[] b = nw.getDataAsByteArr( 20000 ); 309 String contentType = nw.getContentType(); 310 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 311 // create a WFSCapabilities instance from the result 312 result = new String( b ); 313 } else { 314 String msg = StringTools.concat( 500, "Response of the remote WFS contains unknown content type: ", 315 contentType, ";request: ", param ); 316 throw new OGCWebServiceException( "RemoteWFS:handleDescribeFeatureType", msg ); 317 } 318 } catch ( Exception e ) { 319 LOG.logError( e.getMessage(), e ); 320 String msg = StringTools.concat( 500, "Could not get map from RemoteWFS: ", 321 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 322 ';' ); 323 throw new OGCWebServiceException( "RemoteWFS:handleDescribeFeatureType", msg ); 324 325 } 326 327 FeatureTypeDescription ftd = null; 328 try { 329 XMLFragment frag = new XMLFragment( new StringReader( result ), null ); 330 ftd = new FeatureTypeDescription( frag ); 331 } catch ( Exception e1 ) { 332 LOG.logError( e1.getMessage(), e1 ); 333 throw new OGCWebServiceException( this.getClass().getName() + "Could not create response", 334 StringTools.stackTraceToString( e1 ) ); 335 } 336 337 return ftd; 338 } 339 340 /** 341 * reads the capabilities from the remote WFS by performing a GetCapabilities request against 342 * it. The method uses http-GET to call the remote WFS 343 * 344 * @param request 345 * capabilities request 346 * @param client 347 * receiver of the response to the request 348 */ 349 private WFSCapabilities handleGetCapabilities( WFSGetCapabilities request ) 350 throws OGCWebServiceException { 351 352 URL url = addresses.get( GETCAPABILITIES ); 353 String param = request.getRequestParameter(); 354 355 WFSCapabilities response = null; 356 try { 357 String remoteAddress = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ); 358 URL ur = new URL( remoteAddress + param ); 359 WFSCapabilitiesDocument capabilitiesDoc = new WFSCapabilitiesDocument(); 360 capabilitiesDoc.load( ur ); 361 response = (WFSCapabilities) capabilitiesDoc.parseCapabilities(); 362 } catch ( Exception e ) { 363 LOG.logError( e.getMessage(), e ); 364 String msg = StringTools.concat( 500, "Could not get map from RemoteWFS: ", 365 capabilities.getServiceIdentification().getTitle(), "; request: ", param, 366 ';' ); 367 throw new OGCWebServiceException( "RemoteWFS:handleGetCapabilities", msg ); 368 369 } 370 371 return response; 372 373 } 374 375 /** 376 * @param request 377 */ 378 private Object handleLockFeature( LockFeature request ) { 379 // FIXME 380 // TODO 381 return null; 382 } 383 384 /** 385 * @param request 386 */ 387 private Object handleTransaction( Transaction request ) { 388 // FIXME 389 // TODO 390 return null; 391 } 392 393 /* 394 * (non-Javadoc) 395 * 396 * @see org.deegree.ogcwebservices.OGCWebService#getCapabilities() 397 */ 398 public OGCCapabilities getCapabilities() { 399 return capabilities; 400 } 401 402 }