001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wmps/RemoteWMService.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 package org.deegree.ogcwebservices.wmps; 045 046 import java.io.IOException; 047 import java.io.InputStream; 048 import java.io.StringReader; 049 import java.net.URL; 050 import java.util.HashMap; 051 import java.util.List; 052 053 import javax.media.jai.JAI; 054 import javax.media.jai.RenderedOp; 055 056 import org.deegree.datatypes.QualifiedName; 057 import org.deegree.framework.log.ILogger; 058 import org.deegree.framework.log.LoggerFactory; 059 import org.deegree.framework.util.MimeTypeMapper; 060 import org.deegree.framework.util.NetWorker; 061 import org.deegree.framework.util.StringTools; 062 import org.deegree.framework.xml.XMLFragment; 063 import org.deegree.ogcwebservices.OGCWebService; 064 import org.deegree.ogcwebservices.OGCWebServiceException; 065 import org.deegree.ogcwebservices.OGCWebServiceRequest; 066 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 067 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 068 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 069 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 070 import org.deegree.ogcwebservices.wms.operation.GetMap; 071 import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilities; 072 import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory; 073 import org.deegree.owscommon_new.DCP; 074 import org.deegree.owscommon_new.HTTP; 075 import org.deegree.owscommon_new.OperationsMetadata; 076 077 import com.sun.media.jai.codec.MemoryCacheSeekableStream; 078 079 /** 080 * An instance of the class acts as a wrapper to a remote WMS. 081 * 082 * @version $Revision: 9345 $ 083 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 084 */ 085 public class RemoteWMService implements OGCWebService { 086 087 private static ILogger LOG = LoggerFactory.getLogger( RemoteWMService.class ); 088 089 protected HashMap<String, URL> addresses = null; 090 091 protected WMSCapabilities capabilities = null; 092 093 /** 094 * Creates a new instance of RemoteWMService 095 * 096 * @param capabilities 097 */ 098 public RemoteWMService( WMSCapabilities capabilities ) { 099 this.capabilities = capabilities; 100 this.addresses = new HashMap<String, URL>(); 101 102 // get GetCapabilities operation address 103 List<DCP> dcps = null; 104 HTTP http = null; 105 106 OperationsMetadata om = capabilities.getOperationMetadata(); 107 108 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 109 dcps = om.getOperation( new QualifiedName( "Capabilities" ) ).getDCP(); 110 for ( DCP dcp : dcps ) 111 if ( dcp instanceof HTTP ) 112 http = (HTTP) dcp; 113 this.addresses.put( "Capabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 114 } else { 115 dcps = om.getOperation( new QualifiedName( "GetCapabilities" ) ).getDCP(); 116 for ( DCP dcp : dcps ) 117 if ( dcp instanceof HTTP ) 118 http = (HTTP) dcp; 119 this.addresses.put( "GetCapabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 120 } 121 122 // get GetMap operation address 123 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 124 // hui, is this the right name? Though it is all lowercase or 'Map'? 125 dcps = om.getOperation( new QualifiedName( "MAP" ) ).getDCP(); 126 for ( DCP dcp : dcps ) 127 if ( dcp instanceof HTTP ) 128 http = (HTTP) dcp; 129 this.addresses.put( "MAP", http.getLinks().get( 0 ).getLinkage().getHref() ); 130 } else { 131 dcps = om.getOperation( new QualifiedName( "GetMap" ) ).getDCP(); 132 for ( DCP dcp : dcps ) 133 if ( dcp instanceof HTTP ) 134 http = (HTTP) dcp; 135 this.addresses.put( "GetMap", http.getLinks().get( 0 ).getLinkage().getHref() ); 136 } 137 138 } 139 140 /** 141 * Returns the OGCCapabilities 142 * 143 * @return OGCCapabilities 144 */ 145 public OGCCapabilities getCapabilities() { 146 return this.capabilities; 147 } 148 149 /** 150 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the 151 * result to the calling class/method 152 * 153 * @param request 154 * request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform 155 * @return Object 156 * @throws OGCWebServiceException 157 */ 158 public Object doService( OGCWebServiceRequest request ) 159 throws OGCWebServiceException { 160 161 Object object = null; 162 if ( request instanceof GetMap ) { 163 object = handleGetMap( (GetMap) request ); 164 object = WMSProtocolFactory.createGetMapResponse( request, null, object ); 165 } 166 return object; 167 168 } 169 170 /** 171 * performs a GetMap request against the remote service. The result contains the map decoded in 172 * the desired format as a byte array. 173 * 174 * @param request 175 * GetMap request 176 * @return Object 177 * @throws OGCWebServiceException 178 */ 179 protected Object handleGetMap( GetMap request ) 180 throws OGCWebServiceException { 181 182 URL url = null; 183 if ( request.getVersion().equals( "1.0.0" ) ) { 184 url = this.addresses.get( "MAP" ); 185 } else { 186 url = this.addresses.get( "GetMap" ); 187 } 188 189 String param = request.getRequestParameter(); 190 String us = url.toExternalForm(); 191 if ( !us.endsWith( "?" ) ) { 192 us = us + '?'; 193 } 194 us = us + param; 195 LOG.logDebug( "remote wms getmap", us ); 196 197 if ( this.capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) { 198 us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false ); 199 us = StringTools.replace( us, "GetMap", "map", false ); 200 us = StringTools.replace( us, "image/", "", false ); 201 } 202 203 Object result = null; 204 try { 205 URL ur = new URL( us ); 206 // get map from the remote service 207 NetWorker nw = new NetWorker( ur ); 208 InputStream is = nw.getInputStream(); 209 210 String contentType = nw.getContentType(); 211 String[] tmp = StringTools.toArray( contentType, ";", true ); 212 for ( int i = 0; i < tmp.length; i++ ) { 213 if ( tmp[i].indexOf( "image" ) > -1 ) { 214 contentType = tmp[i]; 215 break; 216 } 217 contentType = tmp[0]; 218 } 219 220 if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) { 221 MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is ); 222 RenderedOp rop = JAI.create( "stream", mcss ); 223 result = rop.getAsBufferedImage(); 224 mcss.close(); 225 } else { 226 // extract remote (error) message if the response 227 // contains a known mime type 228 String res = ""; 229 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 230 res = "; remote message: "; 231 res += getInputStreamContent( is ); 232 } 233 String msg = StringTools.concat( 500, "Response of the remote WMS contains wrong content type: ", 234 contentType, ";request: ", param, ' ', res ); 235 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 236 } 237 } catch ( Exception e ) { 238 LOG.logError( e.getMessage(), e ); 239 String msg = StringTools.concat( 500, "Could not get map from RemoteWMS: ", 240 this.capabilities.getServiceIdentification().getTitle(), "; ", 241 "request: ", param, " ", e.toString() ); 242 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", msg ); 243 } 244 245 return result; 246 } 247 248 /** 249 * reads the capabilities from the remote WMS by performing a GetCapabilities request against 250 * it. 251 * 252 * @param request 253 * capabilities request 254 * @return WMSCapabilities 255 * @throws OGCWebServiceException 256 */ 257 protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request ) 258 throws OGCWebServiceException { 259 260 URL url = null; 261 262 if ( request.getVersion().equals( "1.0.0" ) ) { 263 url = this.addresses.get( "capabilites" ); 264 } else { 265 url = this.addresses.get( "GetCapabilities" ); 266 } 267 268 String param = request.getRequestParameter(); 269 String us = url.toExternalForm(); 270 if ( !us.endsWith( "?" ) ) { 271 us = us + '?'; 272 } 273 us = us + param; 274 275 WMSCapabilities result = null; 276 277 try { 278 URL ur = new URL( us ); 279 // get map from the remote service 280 NetWorker nw = new NetWorker( ur ); 281 byte[] b = nw.getDataAsByteArr( 20000 ); 282 String contentType = nw.getContentType(); 283 284 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 285 // create a WMSCapabilitiesTEMP instance from the result 286 StringReader reader = new StringReader( new String( b ) ); 287 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); 288 doc.load( reader, XMLFragment.DEFAULT_URL ); 289 doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() ); 290 result = (WMSCapabilities) doc.parseCapabilities(); 291 } else { 292 String msg = StringTools.concat( 500, "Response of the remote WMS contains unknown content type: ", 293 contentType, ";request: ", param ); 294 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 295 } 296 } catch ( Exception e ) { 297 LOG.logError( e.getMessage(), e ); 298 String msg = StringTools.concat( 500, "Could not get map from RemoteWMS: ", 299 this.capabilities.getServiceIdentification().getTitle(), "; request: ", 300 param + "; ", e.toString() ); 301 throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", msg ); 302 } 303 304 return result; 305 } 306 307 // /** 308 // * Returns the legend graphics 309 // * 310 // * @param request 311 // * describe layer request (WMS 1.1.1 - SLD) 312 // * @return Object 313 // * @throws OGCWebServiceException 314 // */ 315 // protected Object handleGetLegendGraphic( GetLegendGraphic request ) 316 // throws OGCWebServiceException { 317 // 318 // URL url = addresses.get( WMPSConstants.GETLEGENDGRAPHIC ); 319 // 320 // if ( url == null ) { 321 // throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by " 322 // + "the RemoteWMS: " 323 // + capabilities.getServiceIdentification().getTitle() ); 324 // } 325 // 326 // String param = request.getRequestParameter(); 327 // String us = url.toExternalForm(); 328 // if ( !us.endsWith( "?" ) ) { 329 // us = us + '?'; 330 // } 331 // us = us + param; 332 // // FIXME 333 // return null; 334 // } 335 336 /** 337 * 338 * 339 * @param is 340 * 341 * @return String 342 * 343 * @throws IOException 344 */ 345 protected String getInputStreamContent( InputStream is ) 346 throws IOException { 347 StringBuffer sb = new StringBuffer( 1000 ); 348 int c = 0; 349 350 while ( ( c = is.read() ) >= 0 ) { 351 sb.append( (char) c ); 352 } 353 354 is.close(); 355 return sb.toString(); 356 } 357 358 }