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 }