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 **************************************************************************************************/