001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wmps/RemoteWMService.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2006 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.operation.GetMap; 070 import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilities; 071 import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory; 072 import org.deegree.owscommon_new.DCP; 073 import org.deegree.owscommon_new.HTTP; 074 import org.deegree.owscommon_new.OperationsMetadata; 075 076 import com.sun.media.jai.codec.MemoryCacheSeekableStream; 077 078 /** 079 * An instance of the class acts as a wrapper to a remote WMS. 080 * 081 * @version $Revision: 6259 $ 082 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 083 */ 084 public class RemoteWMService implements OGCWebService { 085 086 private static ILogger LOG = LoggerFactory.getLogger( RemoteWMService.class ); 087 088 protected HashMap<String, URL> addresses = null; 089 090 protected WMSCapabilities capabilities = null; 091 092 /** 093 * Creates a new instance of RemoteWMService 094 * 095 * @param capabilities 096 */ 097 public RemoteWMService( WMSCapabilities capabilities ) { 098 this.capabilities = capabilities; 099 this.addresses = new HashMap<String, URL>(); 100 101 // get GetCapabilities operation address 102 List<DCP> dcps = null; 103 HTTP http = null; 104 105 OperationsMetadata om = capabilities.getOperationMetadata(); 106 107 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 108 dcps = om.getOperation( new QualifiedName( "Capabilities" ) ).getDCP(); 109 for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; 110 this.addresses.put( "Capabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 111 } else { 112 dcps = om.getOperation( new QualifiedName( "GetCapabilities" ) ).getDCP(); 113 for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; 114 this.addresses.put( "GetCapabilities", http.getLinks().get( 0 ).getLinkage().getHref() ); 115 } 116 117 // get GetMap operation address 118 if ( capabilities.getVersion().equals( "1.0.0" ) ) { 119 // hui, is this the right name? Though it is all lowercase or 'Map'? 120 dcps = om.getOperation( new QualifiedName( "MAP" ) ).getDCP(); 121 for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; 122 this.addresses.put( "MAP", http.getLinks().get( 0 ).getLinkage().getHref() ); 123 } else { 124 dcps = om.getOperation( new QualifiedName( "GetMap" ) ).getDCP(); 125 for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; 126 this.addresses.put("GetMap", http.getLinks().get( 0 ).getLinkage().getHref() ); 127 } 128 129 } 130 131 /** 132 * Returns the OGCCapabilities 133 * 134 * @return OGCCapabilities 135 */ 136 public OGCCapabilities getCapabilities() { 137 return this.capabilities; 138 } 139 140 /** 141 * the method performs the handling of the passed OGCWebServiceEvent directly and returns the 142 * result to the calling class/method 143 * 144 * @param request 145 * request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform 146 * @return Object 147 * @throws OGCWebServiceException 148 */ 149 public Object doService( OGCWebServiceRequest request ) 150 throws OGCWebServiceException { 151 152 Object object = null; 153 if ( request instanceof GetMap ) { 154 object = handleGetMap( (GetMap) request ); 155 object = WMSProtocolFactory.createGetMapResponse( request, null, object ); 156 } 157 return object; 158 159 } 160 161 /** 162 * performs a GetMap request against the remote service. The result contains the map decoded in 163 * the desired format as a byte array. 164 * 165 * @param request 166 * GetMap request 167 * @return Object 168 * @throws OGCWebServiceException 169 */ 170 protected Object handleGetMap( GetMap request ) 171 throws OGCWebServiceException { 172 173 URL url = null; 174 if ( request.getVersion().equals( "1.0.0" ) ) { 175 url = this.addresses.get( "MAP" ); 176 } else { 177 url = this.addresses.get( "GetMap" ); 178 } 179 180 String param = request.getRequestParameter(); 181 String us = url.toExternalForm(); 182 if ( !us.endsWith( "?" ) ) { 183 us = us + '?'; 184 } 185 us = us + param; 186 LOG.logDebug( "remote wms getmap", us ); 187 188 if ( this.capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) { 189 us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false ); 190 us = StringTools.replace( us, "GetMap", "map", false ); 191 us = StringTools.replace( us, "image/", "", false ); 192 } 193 194 Object result = null; 195 try { 196 URL ur = new URL( us ); 197 // get map from the remote service 198 NetWorker nw = new NetWorker( ur ); 199 InputStream is = nw.getInputStream(); 200 201 String contentType = nw.getContentType(); 202 String[] tmp = StringTools.toArray( contentType, ";", true ); 203 for ( int i = 0; i < tmp.length; i++ ) { 204 if ( tmp[i].indexOf( "image" ) > -1 ) { 205 contentType = tmp[i]; 206 break; 207 } 208 contentType = tmp[0]; 209 } 210 211 if ( MimeTypeMapper.isImageType( contentType ) 212 && 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 226 throw new OGCWebServiceException( "RemoteWMS:handleGetMap", 227 "Response of the remote " + "WMS " + "contains " 228 + "wrong content type: " 229 + contentType 230 + ";request: " + param 231 + res ); 232 } 233 } catch ( Exception e ) { 234 throw new OGCWebServiceException( 235 "RemoteWMS:handleGetMap", 236 "Could not get map from RemoteWMS: " 237 + this.capabilities.getServiceIdentification().getTitle() 238 + "; " + "request: " + param 239 + " " + e.toString() ); 240 } 241 242 return result; 243 } 244 245 /** 246 * reads the capabilities from the remote WMS by performing a GetCapabilities request 247 * against it. 248 * 249 * @param request 250 * capabilities request 251 * @return WMSCapabilities 252 * @throws OGCWebServiceException 253 */ 254 protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request ) 255 throws OGCWebServiceException { 256 257 URL url = null; 258 259 if ( request.getVersion().equals( "1.0.0" ) ) { 260 url = this.addresses.get( "capabilites" ); 261 } else { 262 url = this.addresses.get( "GetCapabilities" ); 263 } 264 265 String param = request.getRequestParameter(); 266 String us = url.toExternalForm(); 267 if ( !us.endsWith( "?" ) ) { 268 us = us + '?'; 269 } 270 us = us + param; 271 272 WMSCapabilities result = null; 273 274 try { 275 URL ur = new URL( us ); 276 // get map from the remote service 277 NetWorker nw = new NetWorker( ur ); 278 byte[] b = nw.getDataAsByteArr( 20000 ); 279 String contentType = nw.getContentType(); 280 281 if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { 282 // create a WMSCapabilitiesTEMP instance from the result 283 StringReader reader = new StringReader( new String( b ) ); 284 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); 285 doc.load( reader, XMLFragment.DEFAULT_URL ); 286 result = (WMSCapabilities) doc.parseCapabilities(); 287 } else { 288 throw new OGCWebServiceException( 289 "RemoteWMS:handleGetCapabilities", 290 "Response of the " 291 + "remote WMS " 292 + "contains " 293 + "unknown content type: " 294 + contentType 295 + ";request: " + param ); 296 } 297 } catch ( Exception e ) { 298 throw new OGCWebServiceException( 299 "RemoteWMS:handleGetCapabilities", 300 "Could not get map from RemoteWMS: " 301 + this.capabilities.getServiceIdentification().getTitle() 302 + "; request: " + param 303 + "; " + e.toString() ); 304 } 305 306 return result; 307 } 308 309 // /** 310 // * Returns the legend graphics 311 // * 312 // * @param request 313 // * describe layer request (WMS 1.1.1 - SLD) 314 // * @return Object 315 // * @throws OGCWebServiceException 316 // */ 317 // protected Object handleGetLegendGraphic( GetLegendGraphic request ) 318 // throws OGCWebServiceException { 319 // 320 // URL url = addresses.get( WMPSConstants.GETLEGENDGRAPHIC ); 321 // 322 // if ( url == null ) { 323 // throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by " 324 // + "the RemoteWMS: " 325 // + capabilities.getServiceIdentification().getTitle() ); 326 // } 327 // 328 // String param = request.getRequestParameter(); 329 // String us = url.toExternalForm(); 330 // if ( !us.endsWith( "?" ) ) { 331 // us = us + '?'; 332 // } 333 // us = us + param; 334 // // FIXME 335 // return null; 336 // } 337 338 /** 339 * 340 * 341 * @param is 342 * 343 * @return String 344 * 345 * @throws IOException 346 */ 347 protected String getInputStreamContent( InputStream is ) 348 throws IOException { 349 StringBuffer sb = new StringBuffer( 1000 ); 350 int c = 0; 351 352 while ( ( c = is.read() ) >= 0 ) { 353 sb.append( (char) c ); 354 } 355 356 is.close(); 357 return sb.toString(); 358 } 359 360 } 361 /*************************************************************************************************** 362 * Changes to this class. What the people have been up to: $Log$ 363 * Changes to this class. What the people have been up to: Revision 1.17 2006/11/27 09:07:52 poth 364 * Changes to this class. What the people have been up to: JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code. 365 * Changes to this class. What the people have been up to: 366 * Changes to this class. What the people have been up to: Revision 1.16 2006/10/22 20:36:05 poth 367 * Changes to this class. What the people have been up to: operations not supported by WMPS removed 368 * Changes to this class. What the people have been up to: 369 * Changes to this class. What the people have been up to: Revision 1.15 2006/08/23 07:10:22 schmitz 370 * Changes to this class. What the people have been up to: Renamed the owscommon_neu package to owscommon_new. 371 * Changes to this class. What the people have been up to: 372 * Changes to this class. What the people have been up to: Revision 1.14 2006/08/22 10:25:01 schmitz 373 * Changes to this class. What the people have been up to: Updated the WMS to use the new OWS common package. 374 * Changes to this class. What the people have been up to: Updated the rest of deegree to use the new data classes returned 375 * Changes to this class. What the people have been up to: by the updated WMS methods/capabilities. 376 * Changes to this class. What the people have been up to: 377 * Changes to this class. What the people have been up to: Revision 1.13 2006/08/10 07:11:35 deshmukh 378 * Changes to this class. What the people have been up to: WMPS has been modified to support the new configuration changes and the excess code not needed has been replaced. 379 * Changes to this class. What the people have been up to: Changes to 380 * this class. What the people have been up to: Revision 1.12 2006/08/01 13:41:48 deshmukh Changes 381 * to this class. What the people have been up to: The wmps configuration has been modified and 382 * extended. Also fixed the javadoc. Changes to this class. What the people have been up to: 383 * Revision 1.11 2006/07/12 14:46:16 poth comment footer added 384 * 385 **************************************************************************************************/