/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.ogcwebservices.wms; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.URL; import java.util.HashMap; import java.util.List; import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import org.deegree.datatypes.QualifiedName; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.MimeTypeMapper; import org.deegree.framework.util.NetWorker; import org.deegree.framework.util.StringTools; import org.deegree.framework.xml.XMLFragment; import org.deegree.ogcwebservices.OGCWebService; import org.deegree.ogcwebservices.OGCWebServiceException; import org.deegree.ogcwebservices.OGCWebServiceRequest; import org.deegree.ogcwebservices.OWSUtils; import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; import org.deegree.ogcwebservices.wms.operation.DescribeLayer; import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo; import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic; import org.deegree.ogcwebservices.wms.operation.GetMap; import org.deegree.ogcwebservices.wms.operation.GetStyles; import org.deegree.ogcwebservices.wms.operation.PutStyles; import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilities; import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory; import org.deegree.owscommon_new.DCP; import org.deegree.owscommon_new.HTTP; import org.deegree.owscommon_new.Operation; import org.deegree.owscommon_new.OperationsMetadata; import com.sun.media.jai.codec.MemoryCacheSeekableStream; /** * An instance of the class acts as a wrapper to a remote WMS. * * @version $Revision: 1.24 $ * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> */ public class RemoteWMService implements OGCWebService { private static ILogger LOG = LoggerFactory.getLogger( RemoteWMService.class ); private static final String GETCAPABILITIES_NAME = "GetCapabilities"; private static final String CAPABILITIES_NAME = "Capabilities"; private static final String GETMAP_NAME = "GetMap"; private static final String MAP_NAME = "Map"; private static final String GETFEATUREINFO_NAME = "GetFeatureInfo"; private static final String FEATUREINFO_NAME = "FeatureInfo"; private static final String DESCRIBELAYER_NAME = "DescribeLayer"; private static final String GETLEGENDGRAPHIC_NAME = "GetLegendGraphic"; private static final String GETSTYLES_NAME = "GetStyles"; private static final String PUTSTYLES_NAME = "PutStyles"; // private static final String UNKNOWN_NAME = "Unknown"; protected HashMap<String, URL> addresses = null; protected WMSCapabilities capabilities = null; /** * Creates a new instance of RemoteWMService * * @param capabilities */ public RemoteWMService( WMSCapabilities capabilities ) { this.capabilities = capabilities; addresses = new HashMap<String, URL>(); // get GetCapabilities operation address List<DCP> dcps = null; HTTP http = null; OperationsMetadata om = capabilities.getOperationMetadata(); if ( capabilities.getVersion().equals( "1.0.0" ) ) { dcps = om.getOperation( new QualifiedName( CAPABILITIES_NAME ) ).getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( CAPABILITIES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } else { dcps = om.getOperation( new QualifiedName( GETCAPABILITIES_NAME ) ).getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( GETCAPABILITIES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } // get GetMap operation address if ( capabilities.getVersion().equals( "1.0.0" ) ) { dcps = om.getOperation( new QualifiedName( MAP_NAME ) ).getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( MAP_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } else { dcps = om.getOperation( new QualifiedName( GETMAP_NAME ) ).getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( GETMAP_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } // get GetFeatureInfo operation address if ( capabilities.getVersion().equals( "1.0.0" ) ) { Operation operation = om.getOperation( new QualifiedName( FEATUREINFO_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( FEATUREINFO_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } } else { Operation operation = om.getOperation( new QualifiedName( GETFEATUREINFO_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( GETFEATUREINFO_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } } // get GetLegendGraphic operation address Operation operation = om.getOperation( new QualifiedName( GETLEGENDGRAPHIC_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( GETLEGENDGRAPHIC_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } // get GetStyles operation address operation = om.getOperation( new QualifiedName( GETSTYLES_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( GETSTYLES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } // get PutStyles operation address operation = om.getOperation( new QualifiedName( PUTSTYLES_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( PUTSTYLES_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } // get DescribeLayer operation address operation = om.getOperation( new QualifiedName( DESCRIBELAYER_NAME ) ); if ( operation != null ) { dcps = operation.getDCP(); for( DCP dcp : dcps ) if( dcp instanceof HTTP ) http = (HTTP) dcp; addresses.put( DESCRIBELAYER_NAME, http.getLinks().get( 0 ).getLinkage().getHref() ); } } public OGCCapabilities getCapabilities() { return capabilities; } /** * the method performs the handling of the passed OGCWebServiceEvent directly * and returns the result to the calling class/method * * @param request request (WMS, WCS, WFS, WCAS, WCTS, WTS, Gazetter) to perform * * @throws OGCWebServiceException */ public Object doService( OGCWebServiceRequest request ) throws OGCWebServiceException { Object o = null; if ( request instanceof GetMap ) { o = handleGetMap( (GetMap)request ); o = WMSProtocolFactory.createGetMapResponse( request, null, o ); } else if ( request instanceof GetFeatureInfo ) { o = handleFeatureInfo( (GetFeatureInfo)request ); o = WMSProtocolFactory.createGetFeatureInfoResponse( request, null, (String)o ); } /* else if ( request instanceof WMSGetCapabilities) { handleGetCapabilities( (WMSGetCapabilities)request, client ); } else if ( request instanceof GetStyles ) { handleGetStyles( (GetStyles)request, client ); } else if ( request instanceof PutStyles ) { handlePutStyles( (PutStyles)request, client ); } else if ( request instanceof DescribeLayer ) { handleDescribeLayer( (DescribeLayer)request, client ); } else if ( request instanceof GetLegendGraphic ) { handleGetLegendGraphic( (GetLegendGraphic)request, client ); } */ return o; } /** * performs a GetMap request against the remote service. The result contains * the map decoded in the desired format as a byte array. * * @param request GetMap request */ protected Object handleGetMap( GetMap request ) throws OGCWebServiceException { URL url = null; if ( request.getVersion().equals( "1.0.0" ) ) { url = addresses.get( MAP_NAME ); } else { url = addresses.get( GETMAP_NAME ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param; LOG.logDebug( "remote wms getmap", us ); if ( capabilities.getVersion().compareTo( "1.0.0" ) <= 0 ) { us = StringTools.replace( us, "TRANSPARENCY", "TRANSPARENT", false ); us = StringTools.replace( us, "GetMap", "map", false ); us = StringTools.replace( us, "image/", "", false ); } Object result = null; try { URL ur = new URL( us ); // get map from the remote service NetWorker nw = new NetWorker( ur ); InputStream is = nw.getInputStream(); String contentType = nw.getContentType(); String[] tmp = StringTools.toArray( contentType, ";", true ); for (int i = 0; i < tmp.length; i++) { if ( tmp[i].indexOf( "image" ) > -1 ) { contentType = tmp[i]; break; } contentType = tmp[0]; } if ( MimeTypeMapper.isImageType( contentType ) && MimeTypeMapper.isKnownImageType( contentType ) ) { MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is ); RenderedOp rop = JAI.create( "stream", mcss ); result = rop.getAsBufferedImage(); mcss.close(); } else { // extract remote (error) message if the response // contains a known mime type String res = ""; if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { res = "; remote message: "; res += getInputStreamContent( is ); } throw new OGCWebServiceException( "RemoteWMS:handleGetMap", "Response of the remote " + "WMS contains wrong content type: " + contentType + ";request: " + param + res ); } } catch ( Exception e ) { throw new OGCWebServiceException( "RemoteWMS:handleGetMap", "Could not get map from RemoteWMS: " + capabilities.getServiceIdentification().getTitle() + "; " + "request: " + param + " " + e.toString() ); } return result; } /** * reads feature infos from the remote WMS by performing a FeatureInfo * request against it. As long the result of a FeatureInfo request is generic * (for usual it is som HTML) it isn't easy to combine the result with that * of other WMS's * * @param request feature info request */ protected Object handleFeatureInfo( GetFeatureInfo request ) throws OGCWebServiceException { URL url = null; if ( request.getVersion().equals( "1.0.0" ) ) { url = addresses.get( FEATUREINFO_NAME ); } else { url = addresses.get( GETFEATUREINFO_NAME ); } if ( url == null ) { throw new OGCWebServiceException( "GetFeatureInfo is not supported by " + "the RemoteWMS: " + capabilities.getServiceIdentification().getTitle() ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; String result = null; try { URL ur = new URL( us ); // get map from the remote service NetWorker nw = new NetWorker( ur ); byte[] b = nw.getDataAsByteArr( 20000 ); String contentType = nw.getContentType(); if ( contentType.toLowerCase().startsWith( "application/vnd.ogc.gml" ) ) { result = new String( b ); } else { throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo" ); } } catch ( Exception e ) { e.printStackTrace(); throw new OGCWebServiceException( "RemoteWMS:handleFeatureInfo", "Could not get map from RemoteWMS: " + capabilities.getServiceIdentification().getTitle() + "; request: " + param + "; " + e.toString() ); } return result; } /** * reads the capabilities from the remote WMS by performing a GetCapabilities * request against it. * * @param request capabilities request */ protected WMSCapabilities handleGetCapabilities( WMSGetCapabilities request) throws OGCWebServiceException { URL url = null; if ( request.getVersion().equals( "1.0.0" ) ) { url = addresses.get( CAPABILITIES_NAME ); } else { url = addresses.get( GETCAPABILITIES_NAME ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; WMSCapabilities result = null; try { URL ur = new URL( us ); // get map from the remote service NetWorker nw = new NetWorker( ur ); byte[] b = nw.getDataAsByteArr( 20000 ); String contentType = nw.getContentType(); if ( MimeTypeMapper.isKnownMimeType( contentType ) ) { // create a WMSCapabilitiesTEMP instance from the result StringReader reader = new StringReader( new String( b ) ); WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument(); doc.load(reader, XMLFragment.DEFAULT_URL ); result = (WMSCapabilities)doc.parseCapabilities(); } else { throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", "Response of the " + "remote WMS contains unknown content type: " + contentType + ";request: " + param ); } } catch ( Exception e ) { throw new OGCWebServiceException( "RemoteWMS:handleGetCapabilities", "Could not get map from RemoteWMS: " + capabilities.getServiceIdentification().getTitle() + "; request: " + param + "; " + e.toString() ); } return result; } /** * * * @param request get styles request (WMS 1.1.1 - SLD) */ protected Object handleGetStyles( GetStyles request ) throws OGCWebServiceException { URL url = addresses.get( GETSTYLES_NAME ); if ( url == null ) { throw new OGCWebServiceException( "GetStyles is not supported by " + "the RemoteWMS: " + capabilities.getServiceIdentification().getTitle() ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; // FIXME // TODO return null; } /** * * * @param request put styles request (WMS 1.1.1 - SLD) */ protected Object handlePutStyles( PutStyles request ) throws OGCWebServiceException { URL url = addresses.get( PUTSTYLES_NAME ); if ( url == null ) { throw new OGCWebServiceException( "PUTSTYLES is not supported by " + "the RemoteWMS: " + capabilities.getServiceIdentification().getTitle() ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; // FIXME // TODO return null; } /** * * * @param request describe layer request (WMS 1.1.1 - SLD) */ protected Object handleDescribeLayer( DescribeLayer request ) throws OGCWebServiceException { URL url = addresses.get( DESCRIBELAYER_NAME ); if ( url == null ) { throw new OGCWebServiceException( "DESCRIBELAYER is not supported by " + "the RemoteWMS: " + capabilities.getServiceIdentification().getTitle() ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; // FIXME // TODO return null; } /** * * * @param request describe layer request (WMS 1.1.1 - SLD) */ protected Object handleGetLegendGraphic( GetLegendGraphic request ) throws OGCWebServiceException { URL url = addresses.get( GETLEGENDGRAPHIC_NAME ); if ( url == null ) { throw new OGCWebServiceException( "GETLEGENDGRAPHIC is not supported by " + "the RemoteWMS: " + capabilities.getServiceIdentification().getTitle() ); } String param = request.getRequestParameter(); String us = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) + param ; // FIXME // TODO return null; } /** * * * @param is * * @return thr content as String * * @throws IOException */ protected String getInputStreamContent( InputStream is ) throws IOException { StringBuffer sb = new StringBuffer( 1000 ); int c = 0; while ( ( c = is.read() ) >= 0 ) { sb.append( (char)c ); } is.close(); return sb.toString(); } }/* ******************************************************************** Changes to this class. What the people have been up to: $Log: RemoteWMService.java,v $ Revision 1.24 2006/11/22 16:20:46 schmitz Fixed checking for remote GetFeatureInfo content type. Revision 1.23 2006/10/22 20:32:08 poth support for vendor specific operation GetScaleBar removed Revision 1.22 2006/10/17 20:31:17 poth *** empty log message *** Revision 1.21 2006/09/06 08:41:40 poth code enhancment / removing references to deprecated class / use OWSUtil instead of mauelly creating a base URL Revision 1.20 2006/08/23 07:10:21 schmitz Renamed the owscommon_neu package to owscommon_new. Revision 1.19 2006/08/22 10:25:01 schmitz Updated the WMS to use the new OWS common package. Updated the rest of deegree to use the new data classes returned by the updated WMS methods/capabilities. Revision 1.18 2006/07/28 08:01:27 schmitz Updated the WMS for 1.1.1 compliance. Fixed some documentation. Revision 1.17 2006/07/12 14:46:17 poth comment footer added ********************************************************************** */