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 }