001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }