001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/wms/RemoteWMService.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 static org.deegree.enterprise.WebUtils.enableProxyUsage;
039 import static org.deegree.framework.util.MapUtils.DEFAULT_PIXEL_SIZE;
040 import static org.deegree.framework.util.MapUtils.calcScale;
041 import static org.deegree.model.spatialschema.GeometryFactory.createEnvelope;
042 import static org.deegree.ogcwebservices.OWSUtils.validateHTTPGetBaseURL;
043
044 import java.awt.image.BufferedImage;
045 import java.io.IOException;
046 import java.io.InputStream;
047 import java.io.StringReader;
048 import java.net.MalformedURLException;
049 import java.net.URL;
050 import java.util.HashMap;
051 import java.util.HashSet;
052 import java.util.Iterator;
053 import java.util.LinkedList;
054 import java.util.List;
055 import java.util.Properties;
056
057 import javax.imageio.ImageIO;
058 import javax.media.jai.JAI;
059 import javax.media.jai.RenderedOp;
060
061 import org.apache.commons.httpclient.Header;
062 import org.apache.commons.httpclient.HttpClient;
063 import org.apache.commons.httpclient.HttpException;
064 import org.apache.commons.httpclient.methods.GetMethod;
065 import org.deegree.datatypes.QualifiedName;
066 import org.deegree.framework.log.ILogger;
067 import org.deegree.framework.log.LoggerFactory;
068 import org.deegree.framework.util.BootLogger;
069 import org.deegree.framework.util.CharsetUtils;
070 import org.deegree.framework.util.MimeTypeMapper;
071 import org.deegree.framework.util.NetWorker;
072 import org.deegree.framework.util.StringTools;
073 import org.deegree.framework.xml.XMLFragment;
074 import org.deegree.i18n.Messages;
075 import org.deegree.model.crs.CRSFactory;
076 import org.deegree.model.crs.CRSTransformationException;
077 import org.deegree.model.crs.CoordinateSystem;
078 import org.deegree.model.crs.GeoTransformer;
079 import org.deegree.model.crs.UnknownCRSException;
080 import org.deegree.model.spatialschema.Envelope;
081 import org.deegree.ogcwebservices.OGCWebService;
082 import org.deegree.ogcwebservices.OGCWebServiceException;
083 import org.deegree.ogcwebservices.OGCWebServiceRequest;
084 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
085 import org.deegree.ogcwebservices.wms.capabilities.Layer;
086 import org.deegree.ogcwebservices.wms.capabilities.LayerBoundingBox;
087 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
088 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
089 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
090 import org.deegree.ogcwebservices.wms.operation.DescribeLayer;
091 import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo;
092 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
093 import org.deegree.ogcwebservices.wms.operation.GetMap;
094 import org.deegree.ogcwebservices.wms.operation.GetStyles;
095 import org.deegree.ogcwebservices.wms.operation.PutStyles;
096 import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilities;
097 import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory;
098 import org.deegree.owscommon_new.DCP;
099 import org.deegree.owscommon_new.HTTP;
100 import org.deegree.owscommon_new.Operation;
101 import org.deegree.owscommon_new.OperationsMetadata;
102 import org.xml.sax.SAXException;
103
104 import com.sun.media.jai.codec.MemoryCacheSeekableStream;
105
106 /**
107 * An instance of the class acts as a wrapper to a remote WMS.
108 *
109 * @version $Revision: 32293 $
110 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
111 */
112 public class RemoteWMService implements OGCWebService {
113
114 private static ILogger LOG = LoggerFactory.getLogger( RemoteWMService.class );
115
116 private static final String GETCAPABILITIES_NAME = "GetCapabilities";
117
118 private static final String CAPABILITIES_NAME = "Capabilities";
119
120 private static final String GETMAP_NAME = "GetMap";
121
122 private static final String MAP_NAME = "Map";
123
124 private static final String GETFEATUREINFO_NAME = "GetFeatureInfo";
125
126 private static final String FEATUREINFO_NAME = "FeatureInfo";
127
128 private static final String DESCRIBELAYER_NAME = "DescribeLayer";
129
130 private static final String GETLEGENDGRAPHIC_NAME = "GetLegendGraphic";
131
132 private static final String GETSTYLES_NAME = "GetStyles";
133
134 private static final String PUTSTYLES_NAME = "PutStyles";
135
136 // private static final String UNKNOWN_NAME = "Unknown";
137
138 protected HashMap<String, URL> addresses = null;
139
140 protected WMSCapabilities capabilities = null;
141
142 private static Properties properties;
143 static {
144 if ( properties == null ) {
145 try {
146 properties = new Properties();
147 InputStream is = RemoteWMService.class.getResourceAsStream( "remotewmservice.properties" );
148 properties.load( is );
149 is.close();
150 } catch ( Exception e ) {
151 BootLogger.logError( e.getMessage(), e );
152 }
153 }
154 }
155
156 /**
157 * Creates a new instance of RemoteWMService
158 *
159 * @param capabilities
160 */
161 public RemoteWMService( WMSCapabilities capabilities ) {
162 this.capabilities = capabilities;
163 addresses = new HashMap<String, URL>();
164
165 // get GetCapabilities operation address
166 List<DCP> dcps = null;
167 HTTP http = null;
168
169 OperationsMetadata om = capabilities.getOperationMetadata();
170
171 if ( capabilities.getVersion().equals( "1.0.0" ) ) {
172 dcps = om.getOperation( new QualifiedName( CAPABILITIES_NAME ) ).getDCP();
173 for ( DCP dcp : dcps )
174 if ( dcp instanceof HTTP )
175 http = (HTTP) dcp;
176 if ( http != null ) {
177 addresses.put( CAPABILITIES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
178 }
179 } else {
180 dcps = om.getOperation( new QualifiedName( GETCAPABILITIES_NAME ) ).getDCP();
181 for ( DCP dcp : dcps )
182 if ( dcp instanceof HTTP )
183 http = (HTTP) dcp;
184 if ( http != null ) {
185 addresses.put( GETCAPABILITIES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
186 }
187 }
188
189 // get GetMap operation address
190 if ( capabilities.getVersion().equals( "1.0.0" ) ) {
191 dcps = om.getOperation( new QualifiedName( MAP_NAME ) ).getDCP();
192 for ( DCP dcp : dcps )
193 if ( dcp instanceof HTTP )
194 http = (HTTP) dcp;
195 if ( http != null ) {
196 addresses.put( MAP_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
197 }
198 } else {
199 dcps = om.getOperation( new QualifiedName( GETMAP_NAME ) ).getDCP();
200 for ( DCP dcp : dcps )
201 if ( dcp instanceof HTTP )
202 http = (HTTP) dcp;
203 if ( http != null ) {
204 addresses.put( GETMAP_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
205 }
206 }
207
208 // get GetFeatureInfo operation address
209 if ( capabilities.getVersion().equals( "1.0.0" ) ) {
210 Operation operation = om.getOperation( new QualifiedName( FEATUREINFO_NAME ) );
211
212 if ( operation != null ) {
213 dcps = operation.getDCP();
214 for ( DCP dcp : dcps )
215 if ( dcp instanceof HTTP )
216 http = (HTTP) dcp;
217 if ( http != null ) {
218 addresses.put( FEATUREINFO_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
219 }
220 }
221 } else {
222 Operation operation = om.getOperation( new QualifiedName( GETFEATUREINFO_NAME ) );
223
224 if ( operation != null ) {
225 dcps = operation.getDCP();
226 for ( DCP dcp : dcps )
227 if ( dcp instanceof HTTP )
228 http = (HTTP) dcp;
229 if ( http != null ) {
230 addresses.put( GETFEATUREINFO_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
231 }
232 }
233 }
234
235 // get GetLegendGraphic operation address
236 Operation operation = om.getOperation( new QualifiedName( GETLEGENDGRAPHIC_NAME ) );
237
238 if ( operation != null ) {
239 dcps = operation.getDCP();
240 for ( DCP dcp : dcps )
241 if ( dcp instanceof HTTP )
242 http = (HTTP) dcp;
243 if ( http != null ) {
244 addresses.put( GETLEGENDGRAPHIC_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
245 }
246 }
247
248 // get GetStyles operation address
249 operation = om.getOperation( new QualifiedName( GETSTYLES_NAME ) );
250
251 if ( operation != null ) {
252 dcps = operation.getDCP();
253 for ( DCP dcp : dcps )
254 if ( dcp instanceof HTTP )
255 http = (HTTP) dcp;
256 if ( http != null ) {
257 addresses.put( GETSTYLES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
258 }
259 }
260
261 // get PutStyles operation address
262 operation = om.getOperation( new QualifiedName( PUTSTYLES_NAME ) );
263
264 if ( operation != null ) {
265 dcps = operation.getDCP();
266 for ( DCP dcp : dcps )
267 if ( dcp instanceof HTTP )
268 http = (HTTP) dcp;
269 if ( http != null ) {
270 addresses.put( PUTSTYLES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
271 }
272 }
273
274 // get DescribeLayer operation address
275 operation = om.getOperation( new QualifiedName( DESCRIBELAYER_NAME ) );
276
277 if ( operation != null ) {
278 dcps = operation.getDCP();
279 for ( DCP dcp : dcps )
280 if ( dcp instanceof HTTP )
281 http = (HTTP) dcp;
282 if ( http != null ) {
283 addresses.put( DESCRIBELAYER_NAME, http.getLinks().get( 0 ).getLinkage().getHref() );
284 }
285 }
286
287 }
288
289 public OGCCapabilities getCapabilities() {
290 return capabilities;
291 }
292
293 private HashSet<CoordinateSystem> getSupportedCoordinateSystems( GetMap getMap )
294 throws UnknownCRSException {
295 HashSet<CoordinateSystem> crs = new HashSet<CoordinateSystem>();
296 List<Layer> layers = new LinkedList<Layer>();
297 for ( GetMap.Layer l : getMap.getLayers() ) {
298 if ( l == null ) {
299 continue; // unclear when/why this can happen
300 }
301 Layer lay = capabilities.getLayer( l.getName() );
302 while ( lay.getParent() != null ) {
303 layers.add( lay );
304 lay = lay.getParent();
305 }
306 }
307 for ( Layer l : layers ) {
308 for ( LayerBoundingBox bbox : l.getBoundingBoxes() ) {
309 if ( bbox.getCoordinateSystem() != null ) {
310 crs.add( bbox.getCoordinateSystem() );
311 }
312 }
313 for ( String srs : l.getSrs() ) {
314 try {
315 crs.add( CRSFactory.create( srs ) );
316 } catch ( Exception e ) {
317 LOG.logWarning( "CRS: " + crs + " is not known and will be ignored" );
318 }
319 }
320 }
321 return crs;
322 }
323
324 /**
325 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the result to the calling
326 * class/method
327 *
328 * @param request
329 * request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform
330 *
331 * @throws OGCWebServiceException
332 */
333 public Object doService( OGCWebServiceRequest request )
334 throws OGCWebServiceException {
335 Object o = null;
336 if ( request instanceof GetMap ) {
337 o = handleGetMap( (GetMap) request );
338 o = WMSProtocolFactory.createGetMapResponse( request, null, o );
339 } else if ( request instanceof GetFeatureInfo ) {
340 o = handleFeatureInfo( (GetFeatureInfo) request );
341 o = WMSProtocolFactory.createGetFeatureInfoResponse( request, null, (String) o );
342 } else if ( request instanceof GetLegendGraphic ) {
343 o = handleGetLegendGraphic( (GetLegendGraphic) request );
344 o = WMSProtocolFactory.createGetLegendGraphicResponse( request, o );
345 }
346 /*
347 * else if ( request instanceof WMSGetCapabilities) { handleGetCapabilities( (WMSGetCapabilities)request, client
348 * ); } else if ( request instanceof GetStyles ) { handleGetStyles( (GetStyles)request, client ); } else if (
349 * request instanceof PutStyles ) { handlePutStyles( (PutStyles)request, client ); } else if ( request
350 * instanceof DescribeLayer ) { handleDescribeLayer( (DescribeLayer)request, client ); } else if ( request
351 * instanceof GetLegendGraphic ) { handleGetLegendGraphic( (GetLegendGraphic)request, client ); }
352 */
353
354 return o;
355
356 }
357
358 // checks for excessive &
359 private static String constructRequestURL( String params, String url ) {
360 if ( url.endsWith( "?" ) && params.startsWith( "&" ) ) {
361 return url + params.substring( 1 );
362 }
363
364 return url + params;
365 }
366
367 /**
368 * performs a GetMap request against the remote service. The result contains the map decoded in the desired format
369 * as a byte array.
370 *
371 * @param request
372 * GetMap request
373 * @return the requested map-image
374 * @throws OGCWebServiceException
375 * if the url in the request is <code>null</code>
376 */
377 protected Object handleGetMap( GetMap request )
378 throws OGCWebServiceException {
379
380 URL url = null;
381
382 if ( request.getVersion().equals( "1.0.0" ) ) {
383 url = addresses.get( MAP_NAME );
384 } else {
385 url = addresses.get( GETMAP_NAME );
386 }
387
388 try {
389 Envelope requestBBOX = request.getBoundingBox();
390 HashSet<CoordinateSystem> crss = getSupportedCoordinateSystems( request );
391 CoordinateSystem requestCRS = CRSFactory.create( request.getSrs() );
392 requestBBOX = createEnvelope( requestBBOX.getMin(), requestBBOX.getMax(), requestCRS );
393 if ( !crss.contains( requestCRS ) ) {
394 Iterator<CoordinateSystem> iterator = crss.iterator();
395 CoordinateSystem dataCRS = iterator.hasNext() ? iterator.next() : null;
396 if ( dataCRS != null ) {
397 GeoTransformer transformer = new GeoTransformer( dataCRS );
398 GeoTransformer transformBack = new GeoTransformer( requestCRS );
399 Envelope dataBBOX = transformer.transform( requestBBOX, requestCRS, true );
400
401 int origWidth = request.getWidth();
402 int origHeight = request.getHeight();
403
404 double scale = calcScale( origWidth, origHeight, requestBBOX, requestCRS, DEFAULT_PIXEL_SIZE );
405 double newScale = calcScale( origWidth, origHeight, dataBBOX, dataCRS, DEFAULT_PIXEL_SIZE );
406 double ratio = scale / newScale;
407 if ( ratio < 1 ) {
408 ratio = newScale / scale;
409 }
410
411 LOG.logDebug( "Requesting transformed bounding box " + dataBBOX + " in srs "
412 + dataCRS.getIdentifier() );
413 request.setBoundingBox( dataBBOX );
414 request.setSrs( dataCRS.getIdentifier() );
415 request.setWidth( (int) ( origWidth * ratio ) );
416 request.setHeight( (int) ( origHeight * ratio ) );
417 Object o = handleGetMap( request );
418 if ( o instanceof BufferedImage ) {
419 return transformBack.transform( (BufferedImage) o, dataBBOX, requestBBOX, origWidth,
420 origHeight, 16, 3, null );
421 }
422
423 return o;
424 }
425 }
426 } catch ( UnknownCRSException e ) {
427 LOG.logError( e.getLocalizedMessage(), e );
428 } catch ( CRSTransformationException e ) {
429 LOG.logError( "An error occurred while transforming bounding boxes (this should not happen)", e );
430 }
431
432 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
433
434 LOG.logDebug( "remote wms getmap", us );
435
436 if ( capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) {
437 us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false );
438 us = StringTools.replace( us, "GetMap", "map", false );
439 us = StringTools.replace( us, "image/", "", false );
440 }
441
442 Object result = null;
443 try {
444 HttpClient client = new HttpClient();
445 enableProxyUsage( client, new URL( us ) );
446 int timeout = 25000;
447 if ( properties != null && properties.getProperty( "timeout" ) != null ) {
448 timeout = Integer.parseInt( properties.getProperty( "timeout" ) );
449 }
450 LOG.logDebug( "timeout is:", timeout );
451 client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
452 GetMethod get = new GetMethod( us );
453 client.executeMethod( get );
454 InputStream is = get.getResponseBodyAsStream();
455 Header header = get.getResponseHeader( "Content-type" );
456
457 String contentType = header.getValue();
458 String[] tmp = StringTools.toArray( contentType, ";", true );
459 for ( int i = 0; i < tmp.length; i++ ) {
460 if ( tmp[i].indexOf( "image" ) > -1 ) {
461 contentType = tmp[i];
462 break;
463 }
464 contentType = tmp[0];
465 }
466
467 if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) {
468 MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is );
469 RenderedOp rop = JAI.create( "stream", mcss );
470 result = rop.getAsBufferedImage();
471 mcss.close();
472 } else {
473 // extract remote (error) message if the response
474 // contains a known mime type
475 String res = "";
476 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) {
477 res = "Remote-WMS message: " + getInputStreamContent( is );
478 } else {
479 res = Messages.getMessage( "REMOTEWMS_GETMAP_INVALID_RESULT", contentType, us );
480 }
481 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", res );
482 }
483 } catch ( HttpException e ) {
484 LOG.logError( e.getMessage(), e );
485 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR",
486 capabilities.getServiceIdentification().getTitle(), us );
487 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg );
488 } catch ( IOException e ) {
489 LOG.logError( e.getMessage(), e );
490 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR",
491 capabilities.getServiceIdentification().getTitle(), us );
492 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg );
493 }
494 // catch ( Exception e ) {
495 // LOG.logError( e.getMessage(), e );
496 // String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR",
497 // capabilities.getServiceIdentification().getTitle(), us );
498 // throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg );
499 // }
500
501 return result;
502 }
503
504 /**
505 * reads feature infos from the remote WMS by performing a FeatureInfo request against it. As long the result of a
506 * FeatureInfo request is generic (for usual it is som HTML) it isn't easy to combine the result with that of other
507 * WMS's
508 *
509 * @param request
510 * feature info request
511 * @return the response of the GetFeatureInfo request.
512 * @throws OGCWebServiceException
513 * if the request could not be excuted correctly.
514 */
515 protected Object handleFeatureInfo( GetFeatureInfo request )
516 throws OGCWebServiceException {
517
518 URL url = null;
519
520 if ( request.getVersion().equals( "1.0.0" ) ) {
521 url = addresses.get( FEATUREINFO_NAME );
522 } else {
523 url = addresses.get( GETFEATUREINFO_NAME );
524 }
525
526 if ( url == null ) {
527 String msg = Messages.getMessage( "REMOTEWMS_GFI_NOT_SUPPORTED",
528 capabilities.getServiceIdentification().getTitle() );
529 throw new OGCWebServiceException( msg );
530 }
531
532 try {
533 GetMap gm = request.getGetMapRequestCopy();
534 Envelope requestBBOX = gm.getBoundingBox();
535 HashSet<CoordinateSystem> crss = getSupportedCoordinateSystems( gm );
536 CoordinateSystem requestCRS = CRSFactory.create( gm.getSrs() );
537 if ( !crss.contains( requestCRS ) ) {
538 CoordinateSystem dataCRS = crss.iterator().next();
539 if ( dataCRS != null ) {
540 GeoTransformer transformer = new GeoTransformer( dataCRS );
541 GeoTransformer transformBack = new GeoTransformer( requestCRS );
542 Envelope dataBBOX = transformer.transform( requestBBOX, requestCRS, true );
543
544 int origWidth = gm.getWidth();
545 int origHeight = gm.getHeight();
546
547 double scale = calcScale( origWidth, origHeight, requestBBOX, requestCRS, DEFAULT_PIXEL_SIZE );
548 double newScale = calcScale( origWidth, origHeight, dataBBOX, dataCRS, DEFAULT_PIXEL_SIZE );
549 double ratio = scale / newScale;
550
551 LOG.logDebug( "Requesting transformed bounding box " + dataBBOX + " in srs "
552 + dataCRS.getIdentifier() );
553 gm.setBoundingBox( dataBBOX );
554 gm.setSrs( dataCRS.getIdentifier() );
555 gm.setWidth( (int) ( origWidth * ratio ) );
556 gm.setHeight( (int) ( origHeight * ratio ) );
557
558 Object o = handleFeatureInfo( request );
559 if ( o instanceof BufferedImage ) {
560 return transformBack.transform( (BufferedImage) o, dataBBOX, requestBBOX, origWidth,
561 origHeight, 16, 3, null );
562 }
563
564 return o;
565 }
566 }
567 } catch ( UnknownCRSException e ) {
568 LOG.logError( e.getLocalizedMessage(), e );
569 } catch ( CRSTransformationException e ) {
570 LOG.logError( "An error occurred while transforming bounding boxes (this should not happen)", e );
571 }
572
573 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
574
575 String result = null;
576 try {
577 LOG.logDebug( "GetFeatureInfo: ", us );
578 URL ur = new URL( us );
579 // get map from the remote service
580 NetWorker nw = new NetWorker( ur );
581 byte[] b = nw.getDataAsByteArr( 20000 );
582 String contentType = nw.getContentType();
583
584 // extract content charset if available; otherwise use configured system charset
585 String charset = null;
586 LOG.logDebug( "content type: ", contentType );
587 if ( contentType != null ) {
588 String[] tmp = StringTools.toArray( contentType, ";", false );
589 if ( tmp.length == 2 ) {
590 charset = tmp[1].substring( tmp[1].indexOf( '=' ) + 1, tmp[1].length() );
591 } else {
592 charset = CharsetUtils.getSystemCharset();
593 }
594 } else {
595 charset = CharsetUtils.getSystemCharset();
596 }
597
598 // commented out checks, we're trying to fix broken GFI responses here, after all
599 // if ( contentType != null && contentType.toLowerCase().startsWith( "application/vnd.ogc.gml" ) ) {
600 result = new String( b, charset );
601 // } else {
602 // throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo" );
603 // }
604 } catch ( Exception e ) {
605 LOG.logError( e.getMessage(), e );
606 String msg = Messages.getMessage( "REMOTEWMS_GFI_GENERAL_ERROR",
607 capabilities.getServiceIdentification().getTitle(), us );
608 throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo", msg );
609 }
610
611 return result;
612 }
613
614 /**
615 * reads the capabilities from the remote WMS by performing a GetCapabilities request against it.
616 *
617 * @param request
618 * capabilities request
619 * @return remote capabilities
620 * @throws OGCWebServiceException
621 * if the request could not be executed correctly.
622 */
623 protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request )
624 throws OGCWebServiceException {
625
626 URL url = null;
627
628 if ( request.getVersion().equals( "1.0.0" ) ) {
629 url = addresses.get( CAPABILITIES_NAME );
630 } else {
631 url = addresses.get( GETCAPABILITIES_NAME );
632 }
633
634 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
635
636 WMSCapabilities result = null;
637
638 try {
639 URL ur = new URL( us );
640 // get map from the remote service
641 NetWorker nw = new NetWorker( ur );
642 byte[] b = nw.getDataAsByteArr( 20000 );
643 String contentType = nw.getContentType();
644
645 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) {
646 // create a WMSCapabilitiesTEMP instance from the result
647 StringReader reader = new StringReader( new String( b ) );
648 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument();
649 doc.load( reader, XMLFragment.DEFAULT_URL );
650 doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() );
651 result = (WMSCapabilities) doc.parseCapabilities();
652 } else {
653 String msg = Messages.getMessage( "REMOTEWMS_GETCAPS_INVALID_CONTENTTYPE", contentType, us );
654 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg );
655 }
656 } catch ( Exception e ) {
657 LOG.logError( e.getMessage(), e );
658 String msg = Messages.getMessage( "REMOTEWMS_GETCAPS_GENERAL_ERROR",
659 capabilities.getServiceIdentification().getTitle(), us );
660 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg );
661 }
662
663 return result;
664 }
665
666 /**
667 *
668 *
669 * @param request
670 * get styles request (WMS 1.1.1 - SLD)
671 * @return <code>null</code>
672 * @throws OGCWebServiceException
673 * if the url in the request is <code>null</code>
674 */
675 protected Object handleGetStyles( GetStyles request )
676 throws OGCWebServiceException {
677
678 URL url = addresses.get( GETSTYLES_NAME );
679
680 if ( url == null ) {
681 throw new OGCWebServiceException( "GetStyles is not supported by the RemoteWMS: "
682 + capabilities.getServiceIdentification().getTitle() );
683 }
684
685 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
686
687 // FIXME
688 // TODO
689 return null;
690 }
691
692 /**
693 *
694 *
695 * @param request
696 * put styles request (WMS 1.1.1 - SLD)
697 * @return <code>null</code>
698 * @throws OGCWebServiceException
699 * if the url in the request is <code>null</code>
700 */
701 protected Object handlePutStyles( PutStyles request )
702 throws OGCWebServiceException {
703
704 URL url = addresses.get( PUTSTYLES_NAME );
705
706 if ( url == null ) {
707 throw new OGCWebServiceException( "PUTSTYLES is not supported by the RemoteWMS: "
708 + capabilities.getServiceIdentification().getTitle() );
709 }
710
711 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
712
713 // FIXME
714 // TODO
715
716 return null;
717 }
718
719 /**
720 *
721 *
722 * @param request
723 * describe layer request (WMS 1.1.1 - SLD)
724 * @return <code>null</code>
725 * @throws OGCWebServiceException
726 * if the url in the request is <code>null</code>
727 */
728 protected Object handleDescribeLayer( DescribeLayer request )
729 throws OGCWebServiceException {
730
731 URL url = addresses.get( DESCRIBELAYER_NAME );
732
733 if ( url == null ) {
734 throw new OGCWebServiceException( "DESCRIBELAYER is not supported by the RemoteWMS: "
735 + capabilities.getServiceIdentification().getTitle() );
736 }
737
738 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) );
739
740 // FIXME
741 // TODO
742
743 return null;
744 }
745
746 /**
747 *
748 *
749 * @param request
750 * describe layer request (WMS 1.1.1 - SLD)
751 * @return <code>null</code>
752 * @throws OGCWebServiceException
753 * if the url in the request is <code>null</code>
754 */
755 protected Object handleGetLegendGraphic( GetLegendGraphic request )
756 throws OGCWebServiceException {
757
758 URL url = addresses.get( GETLEGENDGRAPHIC_NAME );
759
760 if ( url == null ) {
761 throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by the RemoteWMS: "
762 + capabilities.getServiceIdentification().getTitle() );
763 }
764
765 String address = constructRequestURL( request.getRequestParameter(),
766 validateHTTPGetBaseURL( url.toExternalForm() ) );
767
768 try {
769 URL theURL = new URL( address );
770 LOG.logDebug( "Getting legend from remote WMS, URL: ", theURL );
771 BufferedImage img = ImageIO.read( theURL );
772 if ( img == null ) {
773 XMLFragment doc = new XMLFragment( theURL );
774 LOG.logDebug( "Got error message: ", doc.getAsPrettyString() );
775 return new IOException( "Service exception recieved" );
776 }
777 return img;
778 } catch ( MalformedURLException e ) {
779 return e;
780 } catch ( IOException e ) {
781 return e;
782 } catch ( SAXException e ) {
783 return e;
784 }
785 }
786
787 /**
788 *
789 *
790 * @param is
791 *
792 * @return thr content as String
793 *
794 * @throws IOException
795 */
796 protected String getInputStreamContent( InputStream is )
797 throws IOException {
798 StringBuffer sb = new StringBuffer( 1000 );
799 int c = 0;
800
801 while ( ( c = is.read() ) >= 0 ) {
802 sb.append( (char) c );
803 }
804
805 is.close();
806 return sb.toString();
807 }
808
809 }