001 //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/ogcwebservices/wcs/RemoteWCService.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.wcs; 037 038 import java.awt.image.BufferedImage; 039 import java.io.IOException; 040 import java.io.InputStream; 041 import java.io.StringReader; 042 import java.net.URL; 043 import java.util.HashMap; 044 import java.util.Properties; 045 import java.util.UUID; 046 047 import javax.media.jai.JAI; 048 import javax.media.jai.RenderedOp; 049 050 import org.apache.commons.httpclient.Header; 051 import org.apache.commons.httpclient.HttpClient; 052 import org.apache.commons.httpclient.HttpException; 053 import org.apache.commons.httpclient.methods.GetMethod; 054 import org.deegree.enterprise.WebUtils; 055 import org.deegree.framework.log.ILogger; 056 import org.deegree.framework.log.LoggerFactory; 057 import org.deegree.framework.util.BootLogger; 058 import org.deegree.framework.util.MimeTypeMapper; 059 import org.deegree.framework.util.NetWorker; 060 import org.deegree.framework.util.StringTools; 061 import org.deegree.framework.xml.XMLFragment; 062 import org.deegree.i18n.Messages; 063 import org.deegree.model.coverage.grid.ImageGridCoverage; 064 import org.deegree.ogcwebservices.OGCWebService; 065 import org.deegree.ogcwebservices.OGCWebServiceException; 066 import org.deegree.ogcwebservices.OGCWebServiceRequest; 067 import org.deegree.ogcwebservices.OWSUtils; 068 import org.deegree.ogcwebservices.getcapabilities.DCPType; 069 import org.deegree.ogcwebservices.getcapabilities.HTTP; 070 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 071 import org.deegree.ogcwebservices.getcapabilities.Operation; 072 import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata; 073 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription; 074 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescriptionDocument; 075 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering; 076 import org.deegree.ogcwebservices.wcs.describecoverage.DescribeCoverage; 077 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities; 078 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument; 079 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSGetCapabilities; 080 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage; 081 import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage; 082 083 import com.sun.media.jai.codec.MemoryCacheSeekableStream; 084 085 /** 086 * An instance of the class acts as a wrapper to a remote WMS. 087 * 088 * @version $Revision: 11921 $ 089 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 090 */ 091 public class RemoteWCService implements OGCWebService { 092 093 private static ILogger LOG = LoggerFactory.getLogger( RemoteWCService.class ); 094 095 private static final String GETCAPABILITIES_NAME = "GetCapabilities"; 096 097 private static final String GETCOVERAGE_NAME = "GetCoverage"; 098 099 private static final String DESCRIBECOVERAGE_NAME = "DescribeCoverage"; 100 101 protected HashMap<String, URL> addresses = null; 102 103 protected WCSCapabilities capabilities = null; 104 105 private static Properties properties; 106 static { 107 if ( properties == null ) { 108 try { 109 properties = new Properties(); 110 InputStream is = RemoteWCService.class.getResourceAsStream( "remotewcservice.properties" ); 111 properties.load( is ); 112 is.close(); 113 } catch ( Exception e ) { 114 BootLogger.logError( e.getMessage(), e ); 115 } 116 } 117 } 118 119 /** 120 * Creates a new instance of RemoteWMService 121 * 122 * @param capabilities 123 */ 124 public RemoteWCService( WCSCapabilities capabilities ) { 125 this.capabilities = capabilities; 126 addresses = new HashMap<String, URL>(); 127 128 // get GetCapabilities operation address 129 DCPType[] dcps = null; 130 HTTP http = null; 131 132 OperationsMetadata om = capabilities.getCapabilitiy().getOperations(); 133 134 Operation[] ops = om.getOperations(); 135 for ( Operation operation : ops ) { 136 if ( operation.getName().equals( GETCAPABILITIES_NAME ) ) { 137 dcps = operation.getDCPs(); 138 for ( DCPType dcp : dcps ) { 139 if ( dcp.getProtocol() instanceof HTTP ) { 140 http = (HTTP) dcp.getProtocol(); 141 } 142 } 143 } 144 } 145 addresses.put( GETCAPABILITIES_NAME, http.getGetOnlineResources()[0] ); 146 147 // get GetCoverage operation address 148 for ( Operation operation : ops ) { 149 if ( operation.getName().equals( GETCOVERAGE_NAME ) ) { 150 dcps = operation.getDCPs(); 151 for ( DCPType dcp : dcps ) { 152 if ( dcp.getProtocol() instanceof HTTP ) { 153 http = (HTTP) dcp.getProtocol(); 154 } 155 } 156 } 157 } 158 addresses.put( GETCOVERAGE_NAME, http.getGetOnlineResources()[0] ); 159 160 // get DescribeCoverage operation address 161 for ( Operation operation : ops ) { 162 if ( operation.getName().equals( DESCRIBECOVERAGE_NAME ) ) { 163 dcps = operation.getDCPs(); 164 for ( DCPType dcp : dcps ) { 165 if ( dcp.getProtocol() instanceof HTTP ) { 166 http = (HTTP) dcp.getProtocol(); 167 } 168 } 169 } 170 } 171 addresses.put( DESCRIBECOVERAGE_NAME, http.getGetOnlineResources()[0] ); 172 173 } 174 175 public OGCCapabilities getCapabilities() { 176 return capabilities; 177 } 178 179 /** 180 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the 181 * result to the calling class/method 182 * 183 * @param request 184 * request to perform 185 * 186 * @throws OGCWebServiceException 187 */ 188 public Object doService( OGCWebServiceRequest request ) 189 throws OGCWebServiceException { 190 Object o = null; 191 if ( request instanceof GetCoverage ) { 192 o = handleGetCoverage( (GetCoverage) request ); 193 } else if ( request instanceof DescribeCoverage ) { 194 o = handleDescribeCoverage( (DescribeCoverage) request ); 195 } 196 197 return o; 198 199 } 200 201 // checks for excessive & 202 private static String constructRequestURL( String params, String url ) { 203 if ( url.endsWith( "?" ) && params.startsWith( "&" ) ) { 204 return url + params.substring( 1 ); 205 } 206 207 return url + params; 208 } 209 210 /** 211 * performs a GetCoverage request against a remote service. The result contains the Coverage 212 * decoded in the desired format as a byte array. 213 * 214 * @param request 215 * GetCoverage request 216 * @return the requested coverage 217 * @throws OGCWebServiceException 218 * if the url in the request is <code>null</code> 219 */ 220 protected Object handleGetCoverage( GetCoverage request ) 221 throws OGCWebServiceException { 222 223 URL url = addresses.get( GETCOVERAGE_NAME ); 224 225 String us = constructRequestURL( request.getRequestParameter(), OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) ); 226 227 LOG.logDebug( "remote wcs GetCoverage", us ); 228 229 Object result = null; 230 try { 231 HttpClient client = new HttpClient(); 232 WebUtils.enableProxyUsage( client, new URL( us ) ); 233 int timeout = 25000; 234 if ( properties != null && properties.getProperty( "timeout" ) != null ) { 235 timeout = Integer.parseInt( properties.getProperty( "timeout" ) ); 236 } 237 LOG.logDebug( "timeout is:", timeout ); 238 client.getHttpConnectionManager().getParams().setSoTimeout( timeout ); 239 GetMethod get = new GetMethod( us ); 240 client.executeMethod( get ); 241 InputStream is = get.getResponseBodyAsStream(); 242 Header header = get.getResponseHeader( "Content-type" ); 243 244 String contentType = header.getValue(); 245 String[] tmp = StringTools.toArray( contentType, ";", true ); 246 contentType = tmp[0]; 247 248 if ( "application/vnd.ogc.se_xml".equals( contentType ) ) { 249 String res = "Remote-WCS message: " + getInputStreamContent( is ); 250 throw new OGCWebServiceException( "RemoteWCS:handleGetCoverage", res ); 251 } else if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) { 252 MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is ); 253 RenderedOp rop = JAI.create( "stream", mcss ); 254 BufferedImage bi = rop.getAsBufferedImage(); 255 mcss.close(); 256 DescribeCoverage dscC = new DescribeCoverage( UUID.randomUUID().toString(), capabilities.getVersion(), 257 new String[] { request.getSourceCoverage() } ); 258 CoverageDescription cd = handleDescribeCoverage( dscC ); 259 CoverageOffering co = cd.getCoverageOfferings()[0]; 260 result = new ImageGridCoverage( co, request.getDomainSubset().getSpatialSubset().getEnvelope(), bi ); 261 } else { 262 // must be something else; e.g. GML or XYZ-text 263 result = getInputStreamContent( is ); 264 } 265 } catch ( HttpException e ) { 266 LOG.logError( e.getMessage(), e ); 267 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR", capabilities.getService().getLabel(), 268 us ); 269 throw new OGCWebServiceException( "RemoteWCS:handleGetCoverage", msg ); 270 } catch ( IOException e ) { 271 LOG.logError( e.getMessage(), e ); 272 String msg = Messages.getMessage( "REMOTEWMS_GETMAP_GENERAL_ERROR", capabilities.getService().getLabel(), 273 us ); 274 throw new OGCWebServiceException( "RemoteWCS:handleGetCoverage", msg ); 275 } 276 277 return new ResultCoverage( result, result.getClass(), request.getOutput().getFormat(), request ); 278 279 } 280 281 /** 282 * 283 * @param request 284 * DescribeCoverage to perform 285 * @return the response of the DescribeCoverage request. 286 * @throws OGCWebServiceException 287 * if the request could not be excuted correctly. 288 */ 289 protected CoverageDescription handleDescribeCoverage( DescribeCoverage request ) 290 throws OGCWebServiceException { 291 292 URL url = addresses.get( DESCRIBECOVERAGE_NAME ); 293 294 if ( url == null ) { 295 String msg = Messages.getMessage( "REMOTEWMS_GFI_NOT_SUPPORTED", capabilities.getService().getLabel() ); 296 throw new OGCWebServiceException( msg ); 297 } 298 299 String us = constructRequestURL( request.getRequestParameter(), OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) ); 300 301 CoverageDescription result = null; 302 try { 303 LOG.logDebug( "DescribeCoverage: ", us ); 304 // get map from the remote service 305 HttpClient client = new HttpClient(); 306 WebUtils.enableProxyUsage( client, new URL( us ) ); 307 int timeout = 25000; 308 if ( properties != null && properties.getProperty( "timeout" ) != null ) { 309 timeout = Integer.parseInt( properties.getProperty( "timeout" ) ); 310 } 311 LOG.logDebug( "timeout is:", timeout ); 312 client.getHttpConnectionManager().getParams().setSoTimeout( timeout ); 313 GetMethod get = new GetMethod( us ); 314 client.executeMethod( get ); 315 InputStream is = get.getResponseBodyAsStream(); 316 Header header = get.getResponseHeader( "Content-type" ); 317 318 String contentType = header.getValue(); 319 String[] tmp = StringTools.toArray( contentType, ";", true ); 320 contentType = tmp[0]; 321 322 if ( "application/vnd.ogc.se_xml".equals( contentType ) ) { 323 String res = "Remote-WCS message: " + getInputStreamContent( is ); 324 throw new OGCWebServiceException( "RemoteWCS:handleGetCoverage", res ); 325 } else { 326 CoverageDescriptionDocument doc = new CoverageDescriptionDocument(); 327 doc.load( is, us ); 328 result = new CoverageDescription( doc ); 329 } 330 } catch ( Exception e ) { 331 LOG.logError( e.getMessage(), e ); 332 String msg = Messages.getMessage( "REMOTEWCS_GFI_GENERAL_ERROR", capabilities.getService().getLabel(), us ); 333 throw new OGCWebServiceException( "RemoteWCS:handleFeatureInfo", msg ); 334 } 335 336 return result; 337 } 338 339 /** 340 * reads the capabilities from the remote WMS by performing a GetCapabilities request against 341 * it. 342 * 343 * @param request 344 * capabilities request 345 * @return remote capabilities 346 * @throws OGCWebServiceException 347 * if the request could not be executed correctly. 348 */ 349 protected WCSCapabilities handleGetCapabilities( WCSGetCapabilities request ) 350 throws OGCWebServiceException { 351 352 URL url = addresses.get( GETCAPABILITIES_NAME ); 353 354 String us = constructRequestURL( request.getRequestParameter(), OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) ); 355 356 WCSCapabilities result = null; 357 358 try { 359 URL ur = new URL( us ); 360 // get map from the remote service 361 NetWorker nw = new NetWorker( ur ); 362 byte[] b = nw.getDataAsByteArr( 20000 ); 363 String contentType = nw.getContentType(); 364 365 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 366 // create a WMSCapabilitiesTEMP instance from the result 367 StringReader reader = new StringReader( new String( b ) ); 368 WCSCapabilitiesDocument doc = new WCSCapabilitiesDocument(); 369 doc.load( reader, XMLFragment.DEFAULT_URL ); 370 result = (WCSCapabilities) doc.parseCapabilities(); 371 } else { 372 String msg = Messages.getMessage( "REMOTEWMS_GETCAPS_INVALID_CONTENTTYPE", contentType, us ); 373 throw new OGCWebServiceException( "RemoteWCS:handleGetCapabilities", msg ); 374 } 375 } catch ( Exception e ) { 376 LOG.logError( e.getMessage(), e ); 377 String msg = Messages.getMessage( "REMOTEWCS_GETCAPS_GENERAL_ERROR", capabilities.getService().getLabel(), 378 us ); 379 throw new OGCWebServiceException( "RemoteWCS:handleGetCapabilities", msg ); 380 } 381 382 return result; 383 } 384 385 /** 386 * 387 * 388 * @param is 389 * 390 * @return thr content as String 391 * 392 * @throws IOException 393 */ 394 protected String getInputStreamContent( InputStream is ) 395 throws IOException { 396 StringBuffer sb = new StringBuffer( 1000 ); 397 int c = 0; 398 399 while ( ( c = is.read() ) >= 0 ) { 400 sb.append( (char) c ); 401 } 402 403 is.close(); 404 return sb.toString(); 405 } 406 407 }