001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/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: 18195 $ 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 crs.add( CRSFactory.create( srs ) ); 315 } 316 } 317 return crs; 318 } 319 320 /** 321 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the result to the calling 322 * class/method 323 * 324 * @param request 325 * request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform 326 * 327 * @throws OGCWebServiceException 328 */ 329 public Object doService( OGCWebServiceRequest request ) 330 throws OGCWebServiceException { 331 Object o = null; 332 if ( request instanceof GetMap ) { 333 o = handleGetMap( (GetMap) request ); 334 o = WMSProtocolFactory.createGetMapResponse( request, null, o ); 335 } else if ( request instanceof GetFeatureInfo ) { 336 o = handleFeatureInfo( (GetFeatureInfo) request ); 337 o = WMSProtocolFactory.createGetFeatureInfoResponse( request, null, (String) o ); 338 } else if ( request instanceof GetLegendGraphic ) { 339 o = handleGetLegendGraphic( (GetLegendGraphic) request ); 340 o = WMSProtocolFactory.createGetLegendGraphicResponse( request, o ); 341 } 342 /* 343 * else if ( request instanceof WMSGetCapabilities) { handleGetCapabilities( (WMSGetCapabilities)request, client 344 * ); } else if ( request instanceof GetStyles ) { handleGetStyles( (GetStyles)request, client ); } else if ( 345 * request instanceof PutStyles ) { handlePutStyles( (PutStyles)request, client ); } else if ( request 346 * instanceof DescribeLayer ) { handleDescribeLayer( (DescribeLayer)request, client ); } else if ( request 347 * instanceof GetLegendGraphic ) { handleGetLegendGraphic( (GetLegendGraphic)request, client ); } 348 */ 349 350 return o; 351 352 } 353 354 // checks for excessive & 355 private static String constructRequestURL( String params, String url ) { 356 if ( url.endsWith( "?" ) && params.startsWith( "&" ) ) { 357 return url + params.substring( 1 ); 358 } 359 360 return url + params; 361 } 362 363 /** 364 * performs a GetMap request against the remote service. The result contains the map decoded in the desired format 365 * as a byte array. 366 * 367 * @param request 368 * GetMap request 369 * @return the requested map-image 370 * @throws OGCWebServiceException 371 * if the url in the request is <code>null</code> 372 */ 373 protected Object handleGetMap( GetMap request ) 374 throws OGCWebServiceException { 375 376 URL url = null; 377 378 if ( request.getVersion().equals( "1.0.0" ) ) { 379 url = addresses.get( MAP_NAME ); 380 } else { 381 url = addresses.get( GETMAP_NAME ); 382 } 383 384 try { 385 Envelope requestBBOX = request.getBoundingBox(); 386 HashSet<CoordinateSystem> crss = getSupportedCoordinateSystems( request ); 387 CoordinateSystem requestCRS = CRSFactory.create( request.getSrs() ); 388 requestBBOX = createEnvelope( requestBBOX.getMin(), requestBBOX.getMax(), requestCRS ); 389 if ( !crss.contains( requestCRS ) ) { 390 Iterator<CoordinateSystem> iterator = crss.iterator(); 391 CoordinateSystem dataCRS = iterator.hasNext() ? iterator.next() : null; 392 if ( dataCRS != null ) { 393 GeoTransformer transformer = new GeoTransformer( dataCRS ); 394 GeoTransformer transformBack = new GeoTransformer( requestCRS ); 395 Envelope dataBBOX = transformer.transform( requestBBOX, requestCRS, true ); 396 397 int origWidth = request.getWidth(); 398 int origHeight = request.getHeight(); 399 400 double scale = calcScale( origWidth, origHeight, requestBBOX, requestCRS, DEFAULT_PIXEL_SIZE ); 401 double newScale = calcScale( origWidth, origHeight, dataBBOX, dataCRS, DEFAULT_PIXEL_SIZE ); 402 double ratio = scale / newScale; 403 404 LOG.logDebug( "Requesting transformed bounding box " + dataBBOX + " in srs " 405 + dataCRS.getIdentifier() ); 406 request.setBoundingBox( dataBBOX ); 407 request.setSrs( dataCRS.getIdentifier() ); 408 request.setWidth( (int) ( origWidth * ratio ) ); 409 request.setHeight( (int) ( origHeight * ratio ) ); 410 Object o = handleGetMap( request ); 411 if ( o instanceof BufferedImage ) { 412 return transformBack.transform( (BufferedImage) o, dataBBOX, requestBBOX, origWidth, 413 origHeight, 16, 3, null ); 414 } 415 416 return o; 417 } 418 } 419 } catch ( UnknownCRSException e ) { 420 LOG.logError( e.getLocalizedMessage(), e ); 421 } catch ( CRSTransformationException e ) { 422 LOG.logError( "An error occurred while transforming bounding boxes (this should not happen)", e ); 423 } 424 425 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 426 427 LOG.logDebug( "remote wms getmap", us ); 428 429 if ( capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) { 430 us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false ); 431 us = StringTools.replace( us, "GetMap", "map", false ); 432 us = StringTools.replace( us, "image/", "", false ); 433 } 434 435 Object result = null; 436 try { 437 HttpClient client = new HttpClient(); 438 enableProxyUsage( client, new URL( us ) ); 439 int timeout = 25000; 440 if ( properties != null && properties.getProperty( "timeout" ) != null ) { 441 timeout = Integer.parseInt( properties.getProperty( "timeout" ) ); 442 } 443 LOG.logDebug( "timeout is:", timeout ); 444 client.getHttpConnectionManager().getParams().setSoTimeout( timeout ); 445 GetMethod get = new GetMethod( us ); 446 client.executeMethod( get ); 447 InputStream is = get.getResponseBodyAsStream(); 448 Header header = get.getResponseHeader( "Content-type" ); 449 450 String contentType = header.getValue(); 451 String[] tmp = StringTools.toArray( contentType, ";", true ); 452 for ( int i = 0; i < tmp.length; i++ ) { 453 if ( tmp[i].indexOf( "image" ) > -1 ) { 454 contentType = tmp[i]; 455 break; 456 } 457 contentType = tmp[0]; 458 } 459 460 if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) { 461 MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is ); 462 RenderedOp rop = JAI.create( "stream", mcss ); 463 result = rop.getAsBufferedImage(); 464 mcss.close(); 465 } else { 466 // extract remote (error) message if the response 467 // contains a known mime type 468 String res = ""; 469 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 470 res = "Remote-WMS message: " + getInputStreamContent( is ); 471 } else { 472 res = Messages.getMessage( "REMOTEWMS_GETMAP_INVALID_RESULT", contentType, us ); 473 } 474 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", res ); 475 } 476 } catch ( HttpException e ) { 477 LOG.logError( e.getMessage(), e ); 478 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR", 479 capabilities.getServiceIdentification().getTitle(), us ); 480 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 481 } catch ( IOException e ) { 482 LOG.logError( e.getMessage(), e ); 483 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR", 484 capabilities.getServiceIdentification().getTitle(), us ); 485 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 486 } 487 // catch ( Exception e ) { 488 // LOG.logError( e.getMessage(), e ); 489 // String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR", 490 // capabilities.getServiceIdentification().getTitle(), us ); 491 // throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 492 // } 493 494 return result; 495 } 496 497 /** 498 * reads feature infos from the remote WMS by performing a FeatureInfo request against it. As long the result of a 499 * FeatureInfo request is generic (for usual it is som HTML) it isn't easy to combine the result with that of other 500 * WMS's 501 * 502 * @param request 503 * feature info request 504 * @return the response of the GetFeatureInfo request. 505 * @throws OGCWebServiceException 506 * if the request could not be excuted correctly. 507 */ 508 protected Object handleFeatureInfo( GetFeatureInfo request ) 509 throws OGCWebServiceException { 510 511 URL url = null; 512 513 if ( request.getVersion().equals( "1.0.0" ) ) { 514 url = addresses.get( FEATUREINFO_NAME ); 515 } else { 516 url = addresses.get( GETFEATUREINFO_NAME ); 517 } 518 519 if ( url == null ) { 520 String msg = Messages.getMessage( "REMOTEWMS_GFI_NOT_SUPPORTED", 521 capabilities.getServiceIdentification().getTitle() ); 522 throw new OGCWebServiceException( msg ); 523 } 524 525 try { 526 GetMap gm = request.getGetMapRequestCopy(); 527 Envelope requestBBOX = gm.getBoundingBox(); 528 HashSet<CoordinateSystem> crss = getSupportedCoordinateSystems( gm ); 529 CoordinateSystem requestCRS = CRSFactory.create( gm.getSrs() ); 530 if ( !crss.contains( requestCRS ) ) { 531 CoordinateSystem dataCRS = crss.iterator().next(); 532 if ( dataCRS != null ) { 533 GeoTransformer transformer = new GeoTransformer( dataCRS ); 534 GeoTransformer transformBack = new GeoTransformer( requestCRS ); 535 Envelope dataBBOX = transformer.transform( requestBBOX, requestCRS, true ); 536 537 int origWidth = gm.getWidth(); 538 int origHeight = gm.getHeight(); 539 540 double scale = calcScale( origWidth, origHeight, requestBBOX, requestCRS, DEFAULT_PIXEL_SIZE ); 541 double newScale = calcScale( origWidth, origHeight, dataBBOX, dataCRS, DEFAULT_PIXEL_SIZE ); 542 double ratio = scale / newScale; 543 544 LOG.logDebug( "Requesting transformed bounding box " + dataBBOX + " in srs " 545 + dataCRS.getIdentifier() ); 546 gm.setBoundingBox( dataBBOX ); 547 gm.setSrs( dataCRS.getIdentifier() ); 548 gm.setWidth( (int) ( origWidth * ratio ) ); 549 gm.setHeight( (int) ( origHeight * ratio ) ); 550 551 Object o = handleFeatureInfo( request ); 552 if ( o instanceof BufferedImage ) { 553 return transformBack.transform( (BufferedImage) o, dataBBOX, requestBBOX, origWidth, 554 origHeight, 16, 3, null ); 555 } 556 557 return o; 558 } 559 } 560 } catch ( UnknownCRSException e ) { 561 LOG.logError( e.getLocalizedMessage(), e ); 562 } catch ( CRSTransformationException e ) { 563 LOG.logError( "An error occurred while transforming bounding boxes (this should not happen)", e ); 564 } 565 566 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 567 568 String result = null; 569 try { 570 LOG.logDebug( "GetFeatureInfo: ", us ); 571 URL ur = new URL( us ); 572 // get map from the remote service 573 NetWorker nw = new NetWorker( ur ); 574 byte[] b = nw.getDataAsByteArr( 20000 ); 575 String contentType = nw.getContentType(); 576 577 // extract content charset if available; otherwise use configured system charset 578 String charset = null; 579 LOG.logDebug( "content type: ", contentType ); 580 if ( contentType != null ) { 581 String[] tmp = StringTools.toArray( contentType, ";", false ); 582 if ( tmp.length == 2 ) { 583 charset = tmp[1].substring( tmp[1].indexOf( '=' ) + 1, tmp[1].length() ); 584 } else { 585 charset = CharsetUtils.getSystemCharset(); 586 } 587 } else { 588 charset = CharsetUtils.getSystemCharset(); 589 } 590 591 // commented out checks, we're trying to fix broken GFI responses here, after all 592 // if ( contentType != null && contentType.toLowerCase().startsWith( "application/vnd.ogc.gml" ) ) { 593 result = new String( b, charset ); 594 // } else { 595 // throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo" ); 596 // } 597 } catch ( Exception e ) { 598 LOG.logError( e.getMessage(), e ); 599 String msg = Messages.getMessage( "REMOTEWMS_GFI_GENERAL_ERROR", 600 capabilities.getServiceIdentification().getTitle(), us ); 601 throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo", msg ); 602 } 603 604 return result; 605 } 606 607 /** 608 * reads the capabilities from the remote WMS by performing a GetCapabilities request against it. 609 * 610 * @param request 611 * capabilities request 612 * @return remote capabilities 613 * @throws OGCWebServiceException 614 * if the request could not be executed correctly. 615 */ 616 protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request ) 617 throws OGCWebServiceException { 618 619 URL url = null; 620 621 if ( request.getVersion().equals( "1.0.0" ) ) { 622 url = addresses.get( CAPABILITIES_NAME ); 623 } else { 624 url = addresses.get( GETCAPABILITIES_NAME ); 625 } 626 627 String us = constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 628 629 WMSCapabilities result = null; 630 631 try { 632 URL ur = new URL( us ); 633 // get map from the remote service 634 NetWorker nw = new NetWorker( ur ); 635 byte[] b = nw.getDataAsByteArr( 20000 ); 636 String contentType = nw.getContentType(); 637 638 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 639 // create a WMSCapabilitiesTEMP instance from the result 640 StringReader reader = new StringReader( new String( b ) ); 641 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); 642 doc.load( reader, XMLFragment.DEFAULT_URL ); 643 doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() ); 644 result = (WMSCapabilities) doc.parseCapabilities(); 645 } else { 646 String msg = Messages.getMessage( "REMOTEWMS_GETCAPS_INVALID_CONTENTTYPE", contentType, us ); 647 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 648 } 649 } catch ( Exception e ) { 650 LOG.logError( e.getMessage(), e ); 651 String msg = Messages.getMessage( "REMOTEWMS_GETCAPS_GENERAL_ERROR", 652 capabilities.getServiceIdentification().getTitle(), us ); 653 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 654 } 655 656 return result; 657 } 658 659 /** 660 * 661 * 662 * @param request 663 * get styles request (WMS 1.1.1 - SLD) 664 * @return <code>null</code> 665 * @throws OGCWebServiceException 666 * if the url in the request is <code>null</code> 667 */ 668 protected Object handleGetStyles( GetStyles request ) 669 throws OGCWebServiceException { 670 671 URL url = addresses.get( GETSTYLES_NAME ); 672 673 if ( url == null ) { 674 throw new OGCWebServiceException( "GetStyles is not supported by the RemoteWMS: " 675 + capabilities.getServiceIdentification().getTitle() ); 676 } 677 678 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 679 680 // FIXME 681 // TODO 682 return null; 683 } 684 685 /** 686 * 687 * 688 * @param request 689 * put styles request (WMS 1.1.1 - SLD) 690 * @return <code>null</code> 691 * @throws OGCWebServiceException 692 * if the url in the request is <code>null</code> 693 */ 694 protected Object handlePutStyles( PutStyles request ) 695 throws OGCWebServiceException { 696 697 URL url = addresses.get( PUTSTYLES_NAME ); 698 699 if ( url == null ) { 700 throw new OGCWebServiceException( "PUTSTYLES is not supported by the RemoteWMS: " 701 + capabilities.getServiceIdentification().getTitle() ); 702 } 703 704 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 705 706 // FIXME 707 // TODO 708 709 return null; 710 } 711 712 /** 713 * 714 * 715 * @param request 716 * describe layer request (WMS 1.1.1 - SLD) 717 * @return <code>null</code> 718 * @throws OGCWebServiceException 719 * if the url in the request is <code>null</code> 720 */ 721 protected Object handleDescribeLayer( DescribeLayer request ) 722 throws OGCWebServiceException { 723 724 URL url = addresses.get( DESCRIBELAYER_NAME ); 725 726 if ( url == null ) { 727 throw new OGCWebServiceException( "DESCRIBELAYER is not supported by the RemoteWMS: " 728 + capabilities.getServiceIdentification().getTitle() ); 729 } 730 731 constructRequestURL( request.getRequestParameter(), validateHTTPGetBaseURL( url.toExternalForm() ) ); 732 733 // FIXME 734 // TODO 735 736 return null; 737 } 738 739 /** 740 * 741 * 742 * @param request 743 * describe layer request (WMS 1.1.1 - SLD) 744 * @return <code>null</code> 745 * @throws OGCWebServiceException 746 * if the url in the request is <code>null</code> 747 */ 748 protected Object handleGetLegendGraphic( GetLegendGraphic request ) 749 throws OGCWebServiceException { 750 751 URL url = addresses.get( GETLEGENDGRAPHIC_NAME ); 752 753 if ( url == null ) { 754 throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by the RemoteWMS: " 755 + capabilities.getServiceIdentification().getTitle() ); 756 } 757 758 String address = constructRequestURL( request.getRequestParameter(), 759 validateHTTPGetBaseURL( url.toExternalForm() ) ); 760 761 try { 762 URL theURL = new URL( address ); 763 LOG.logDebug( "Getting legend from remote WMS, URL: ", theURL ); 764 BufferedImage img = ImageIO.read( theURL ); 765 if ( img == null ) { 766 XMLFragment doc = new XMLFragment( theURL ); 767 LOG.logDebug( "Got error message: ", doc.getAsPrettyString() ); 768 return new IOException( "Service exception recieved" ); 769 } 770 return img; 771 } catch ( MalformedURLException e ) { 772 return e; 773 } catch ( IOException e ) { 774 return e; 775 } catch ( SAXException e ) { 776 return e; 777 } 778 } 779 780 /** 781 * 782 * 783 * @param is 784 * 785 * @return thr content as String 786 * 787 * @throws IOException 788 */ 789 protected String getInputStreamContent( InputStream is ) 790 throws IOException { 791 StringBuffer sb = new StringBuffer( 1000 ); 792 int c = 0; 793 794 while ( ( c = is.read() ) >= 0 ) { 795 sb.append( (char) c ); 796 } 797 798 is.close(); 799 return sb.toString(); 800 } 801 802 }