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 }