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 }