001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wmps/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.wmps; 037 038 import java.io.IOException; 039 import java.io.InputStream; 040 import java.io.StringReader; 041 import java.net.URL; 042 import java.util.HashMap; 043 import java.util.List; 044 045 import javax.media.jai.JAI; 046 import javax.media.jai.RenderedOp; 047 048 import org.deegree.datatypes.QualifiedName; 049 import org.deegree.framework.log.ILogger; 050 import org.deegree.framework.log.LoggerFactory; 051 import org.deegree.framework.util.MimeTypeMapper; 052 import org.deegree.framework.util.NetWorker; 053 import org.deegree.framework.util.StringTools; 054 import org.deegree.framework.xml.XMLFragment; 055 import org.deegree.ogcwebservices.OGCWebService; 056 import org.deegree.ogcwebservices.OGCWebServiceException; 057 import org.deegree.ogcwebservices.OGCWebServiceRequest; 058 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 059 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 060 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 061 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 062 import org.deegree.ogcwebservices.wms.operation.GetMap; 063 import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilities; 064 import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory; 065 import org.deegree.owscommon_new.DCP; 066 import org.deegree.owscommon_new.HTTP; 067 import org.deegree.owscommon_new.OperationsMetadata; 068 069 import com.sun.media.jai.codec.MemoryCacheSeekableStream; 070 071 /** 072 * An instance of the class acts as a wrapper to a remote WMS. 073 * 074 * @version $Revision: 18195 $ 075 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 076 */ 077 public class RemoteWMService implements OGCWebService { 078 079 private static ILogger LOG = LoggerFactory.getLogger( RemoteWMService.class ); 080 081 protected HashMap<String, URL> addresses = null; 082 083 protected WMSCapabilities capabilities = null; 084 085 /** 086 * Creates a new instance of RemoteWMService 087 * 088 * @param capabilities 089 */ 090 public RemoteWMService( WMSCapabilities capabilities ) { 091 this.capabilities = capabilities; 092 this.addresses = new HashMap<String, URL>(); 093 094 // get GetCapabilities operation address 095 List<DCP> dcps = null; 096 HTTP http = null; 097 098 OperationsMetadata om = capabilities.getOperationMetadata(); 099 100 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 101 dcps = om.getOperation( new QualifiedName( "Capabilities" ) ).getDCP(); 102 for ( DCP dcp : dcps ) 103 if ( dcp instanceof HTTP ) 104 http = (HTTP) dcp; 105 this.addresses.put( "Capabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 106 } else { 107 dcps = om.getOperation( new QualifiedName( "GetCapabilities" ) ).getDCP(); 108 for ( DCP dcp : dcps ) 109 if ( dcp instanceof HTTP ) 110 http = (HTTP) dcp; 111 this.addresses.put( "GetCapabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 112 } 113 114 // get GetMap operation address 115 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 116 // hui, is this the right name? Though it is all lowercase or 'Map'? 117 dcps = om.getOperation( new QualifiedName( "MAP" ) ).getDCP(); 118 for ( DCP dcp : dcps ) 119 if ( dcp instanceof HTTP ) 120 http = (HTTP) dcp; 121 this.addresses.put( "MAP", http.getLinks().get( 0 ).getLinkage().getHref() ); 122 } else { 123 dcps = om.getOperation( new QualifiedName( "GetMap" ) ).getDCP(); 124 for ( DCP dcp : dcps ) 125 if ( dcp instanceof HTTP ) 126 http = (HTTP) dcp; 127 this.addresses.put( "GetMap", http.getLinks().get( 0 ).getLinkage().getHref() ); 128 } 129 130 } 131 132 /** 133 * Returns the OGCCapabilities 134 * 135 * @return OGCCapabilities 136 */ 137 public OGCCapabilities getCapabilities() { 138 return this.capabilities; 139 } 140 141 /** 142 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the 143 * result to the calling class/method 144 * 145 * @param request 146 * request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform 147 * @return Object 148 * @throws OGCWebServiceException 149 */ 150 public Object doService( OGCWebServiceRequest request ) 151 throws OGCWebServiceException { 152 153 Object object = null; 154 if ( request instanceof GetMap ) { 155 object = handleGetMap( (GetMap) request ); 156 object = WMSProtocolFactory.createGetMapResponse( request, null, object ); 157 } 158 return object; 159 160 } 161 162 /** 163 * performs a GetMap request against the remote service. The result contains the map decoded in 164 * the desired format as a byte array. 165 * 166 * @param request 167 * GetMap request 168 * @return Object 169 * @throws OGCWebServiceException 170 */ 171 protected Object handleGetMap( GetMap request ) 172 throws OGCWebServiceException { 173 174 URL url = null; 175 if ( request.getVersion().equals( "1.0.0" ) ) { 176 url = this.addresses.get( "MAP" ); 177 } else { 178 url = this.addresses.get( "GetMap" ); 179 } 180 181 String param = request.getRequestParameter(); 182 String us = url.toExternalForm(); 183 if ( !us.endsWith( "?" ) ) { 184 us = us + '?'; 185 } 186 us = us + param; 187 LOG.logDebug( "remote wms getmap", us ); 188 189 if ( this.capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) { 190 us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false ); 191 us = StringTools.replace( us, "GetMap", "map", false ); 192 us = StringTools.replace( us, "image/", "", false ); 193 } 194 195 Object result = null; 196 try { 197 URL ur = new URL( us ); 198 // get map from the remote service 199 NetWorker nw = new NetWorker( ur ); 200 InputStream is = nw.getInputStream(); 201 202 String contentType = nw.getContentType(); 203 String[] tmp = StringTools.toArray( contentType, ";", true ); 204 for ( int i = 0; i < tmp.length; i++ ) { 205 if ( tmp[i].indexOf( "image" ) > -1 ) { 206 contentType = tmp[i]; 207 break; 208 } 209 contentType = tmp[0]; 210 } 211 212 if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) { 213 MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is ); 214 RenderedOp rop = JAI.create( "stream", mcss ); 215 result = rop.getAsBufferedImage(); 216 mcss.close(); 217 } else { 218 // extract remote (error) message if the response 219 // contains a known mime type 220 String res = ""; 221 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 222 res = "; remote message: "; 223 res += getInputStreamContent( is ); 224 } 225 String msg = StringTools.concat( 500, "Response of the remote WMS contains wrong content type: ", 226 contentType, ";request: ", param, ' ', res ); 227 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 228 } 229 } catch ( Exception e ) { 230 LOG.logError( e.getMessage(), e ); 231 String msg = StringTools.concat( 500, "Could not get map from RemoteWMS: ", 232 this.capabilities.getServiceIdentification().getTitle(), "; ", 233 "request: ", param, " ", e.toString() ); 234 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 235 } 236 237 return result; 238 } 239 240 /** 241 * reads the capabilities from the remote WMS by performing a GetCapabilities request against 242 * it. 243 * 244 * @param request 245 * capabilities request 246 * @return WMSCapabilities 247 * @throws OGCWebServiceException 248 */ 249 protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request ) 250 throws OGCWebServiceException { 251 252 URL url = null; 253 254 if ( request.getVersion().equals( "1.0.0" ) ) { 255 url = this.addresses.get( "capabilites" ); 256 } else { 257 url = this.addresses.get( "GetCapabilities" ); 258 } 259 260 String param = request.getRequestParameter(); 261 String us = url.toExternalForm(); 262 if ( !us.endsWith( "?" ) ) { 263 us = us + '?'; 264 } 265 us = us + param; 266 267 WMSCapabilities result = null; 268 269 try { 270 URL ur = new URL( us ); 271 // get map from the remote service 272 NetWorker nw = new NetWorker( ur ); 273 byte[] b = nw.getDataAsByteArr( 20000 ); 274 String contentType = nw.getContentType(); 275 276 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 277 // create a WMSCapabilitiesTEMP instance from the result 278 StringReader reader = new StringReader( new String( b ) ); 279 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); 280 doc.load( reader, XMLFragment.DEFAULT_URL ); 281 doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() ); 282 result = (WMSCapabilities) doc.parseCapabilities(); 283 } else { 284 String msg = StringTools.concat( 500, "Response of the remote WMS contains unknown content type: ", 285 contentType, ";request: ", param ); 286 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 287 } 288 } catch ( Exception e ) { 289 LOG.logError( e.getMessage(), e ); 290 String msg = StringTools.concat( 500, "Could not get map from RemoteWMS: ", 291 this.capabilities.getServiceIdentification().getTitle(), "; request: ", 292 param + "; ", e.toString() ); 293 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 294 } 295 296 return result; 297 } 298 299 // /** 300 // * Returns the legend graphics 301 // * 302 // * @param request 303 // * describe layer request (WMS 1.1.1 - SLD) 304 // * @return Object 305 // * @throws OGCWebServiceException 306 // */ 307 // protected Object handleGetLegendGraphic( GetLegendGraphic request ) 308 // throws OGCWebServiceException { 309 // 310 // URL url = addresses.get( WMPSConstants.GETLEGENDGRAPHIC ); 311 // 312 // if ( url == null ) { 313 // throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by " 314 // + "the RemoteWMS: " 315 // + capabilities.getServiceIdentification().getTitle() ); 316 // } 317 // 318 // String param = request.getRequestParameter(); 319 // String us = url.toExternalForm(); 320 // if ( !us.endsWith( "?" ) ) { 321 // us = us + '?'; 322 // } 323 // us = us + param; 324 // // FIXME 325 // return null; 326 // } 327 328 /** 329 * 330 * 331 * @param is 332 * 333 * @return String 334 * 335 * @throws IOException 336 */ 337 protected String getInputStreamContent( InputStream is ) 338 throws IOException { 339 StringBuffer sb = new StringBuffer( 1000 ); 340 int c = 0; 341 342 while ( ( c = is.read() ) >= 0 ) { 343 sb.append( (char) c ); 344 } 345 346 is.close(); 347 return sb.toString(); 348 } 349 350 }