001 // $HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wms/GetLegendGraphicHandler.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.wms; 037 038 import java.awt.image.BufferedImage; 039 import java.net.URL; 040 import java.util.List; 041 042 import org.deegree.datatypes.QualifiedName; 043 import org.deegree.framework.log.ILogger; 044 import org.deegree.framework.log.LoggerFactory; 045 import org.deegree.framework.util.ImageUtils; 046 import org.deegree.framework.util.StringTools; 047 import org.deegree.graphics.legend.LegendElement; 048 import org.deegree.graphics.legend.LegendFactory; 049 import org.deegree.graphics.sld.SLDFactory; 050 import org.deegree.graphics.sld.StyledLayerDescriptor; 051 import org.deegree.graphics.sld.UserStyle; 052 import org.deegree.i18n.Messages; 053 import org.deegree.ogcwebservices.OGCWebServiceException; 054 import org.deegree.ogcwebservices.wms.capabilities.Layer; 055 import org.deegree.ogcwebservices.wms.capabilities.LegendURL; 056 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource; 057 import org.deegree.ogcwebservices.wms.configuration.ExternalDataAccessDataSource; 058 import org.deegree.ogcwebservices.wms.configuration.LocalWCSDataSource; 059 import org.deegree.ogcwebservices.wms.configuration.RemoteWCSDataSource; 060 import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource; 061 import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationType; 062 import org.deegree.ogcwebservices.wms.dataaccess.ExternalDataAccess; 063 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic; 064 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphicResult; 065 import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory; 066 import org.deegree.owscommon_new.DCP; 067 import org.deegree.owscommon_new.HTTP; 068 import org.deegree.owscommon_new.Operation; 069 import org.deegree.owscommon_new.OperationsMetadata; 070 071 /** 072 * performs a GetLegendGraphic request. The capability of the deegree implementation is limited to handle requests 073 * containing a named style or using the (named) styles defined in a passed or referenced SLD. featuretype and rule are 074 * not supported yet. 075 * 076 * @version $Revision: 18195 $ 077 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 078 * @author last edited by: $Author: mschneider $ 079 * 080 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 081 * 082 * @since 1.1 083 */ 084 class GetLegendGraphicHandler { 085 086 private static final ILogger LOG = LoggerFactory.getLogger( GetLegendGraphicHandler.class ); 087 088 private WMSConfigurationType configuration = null; 089 090 private StyledLayerDescriptor sld = null; 091 092 private GetLegendGraphic request = null; 093 094 /** 095 * Creates a new GetMapHandler object. 096 * 097 * @param capabilities 098 * @param request 099 * request to perform 100 */ 101 public GetLegendGraphicHandler( WMSConfigurationType capabilities, GetLegendGraphic request ) { 102 this.configuration = capabilities; 103 this.request = request; 104 } 105 106 /** 107 * performs the request and returns the result of it. 108 * 109 * @return the result object 110 * @throws OGCWebServiceException 111 */ 112 public GetLegendGraphicResult performGetLegendGraphic() 113 throws OGCWebServiceException { 114 115 validate( request ); 116 LegendElement lege = getSymbol( request ); 117 BufferedImage bi = null; 118 try { 119 bi = lege.exportAsImage( request.getFormat() ); 120 } catch ( Exception e ) { 121 LOG.logError( e.getMessage(), e ); 122 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 123 } 124 125 GetLegendGraphicResult res = WMSProtocolFactory.createGetLegendGraphicResponse( request, bi ); 126 127 return res; 128 } 129 130 /** 131 * validates if the passed request is valid against the WMS it was sent to and the SLD maybe contained or referenced 132 * in/by the request. 133 * 134 * @param request 135 * request to validate 136 */ 137 private void validate( GetLegendGraphic request ) 138 throws OGCWebServiceException { 139 140 String layerName = request.getLayer(); 141 String style = request.getStyle(); 142 if ( request.getSLD() == null && request.getSLD_Body() == null ) { 143 Layer layer = configuration.getLayer( layerName ); 144 if ( layer == null ) { 145 String s = Messages.getMessage( "WMS_UNKNOWNLAYER", layerName ); 146 throw new LayerNotDefinedException( s ); 147 } 148 AbstractDataSource[] ds = layer.getDataSource(); 149 boolean raster = true; 150 for ( AbstractDataSource abstractDataSource : ds ) { 151 if ( !( abstractDataSource instanceof ExternalDataAccessDataSource ) 152 && !( abstractDataSource instanceof RemoteWMSDataSource ) 153 && !( abstractDataSource instanceof RemoteWCSDataSource ) 154 && !( abstractDataSource instanceof LocalWCSDataSource ) ) { 155 raster = false; 156 break; 157 } 158 } 159 if ( !raster && getNamedStyle( style ) == null ) { 160 String s = Messages.getMessage( "WMS_STYLENOTKNOWN", style ); 161 throw new StyleNotDefinedException( s ); 162 } 163 } else { 164 try { 165 if ( request.getSLD() != null ) { 166 sld = SLDFactory.createSLD( request.getSLD() ); 167 } else { 168 sld = SLDFactory.createSLD( request.getSLD_Body() ); 169 } 170 // check if layer and style are present 171 org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers(); 172 boolean found = false; 173 for ( int i = 0; i < sldLayers.length; i++ ) { 174 if ( layerName.equals( sldLayers[i].getName() ) ) { 175 org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles(); 176 for ( int k = 0; k < sldStyles.length; k++ ) { 177 if ( sldStyles[k].getName() != null && sldStyles[k].getName().equals( style ) ) { 178 found = true; 179 break; 180 } 181 } 182 if ( found ) 183 break; 184 } 185 } 186 if ( !found ) { 187 String s = Messages.getMessage( "WMS_LAYERNOTKNOWN", layerName ); 188 throw new OGCWebServiceException( getClass().getName(), s ); 189 } 190 191 } catch ( Exception e ) { 192 LOG.logError( e.getMessage(), e ); 193 String s = Messages.getMessage( "WMS_INVALIDSLDREF" ); 194 throw new OGCWebServiceException( getClass().getName(), s ); 195 } 196 197 } 198 199 } 200 201 private org.deegree.ogcwebservices.wms.capabilities.Style getNamedStyle( String name ) { 202 String layerName = request.getLayer(); 203 Layer layer = configuration.getLayer( layerName ); 204 org.deegree.ogcwebservices.wms.capabilities.Style[] styles = layer.getStyles(); 205 for ( int i = 0; i < styles.length; i++ ) { 206 if ( styles[i].getName().equals( name ) ) { 207 return styles[i]; 208 } 209 } 210 return null; 211 } 212 213 /** 214 * @param request 215 * @return the symbol 216 * @throws OGCWebServiceException 217 */ 218 private LegendElement getSymbol( GetLegendGraphic request ) 219 throws OGCWebServiceException { 220 221 LegendElement le = null; 222 try { 223 if ( request.getSLD() == null && request.getSLD_Body() == null ) { 224 225 // (temporary?) workaround for remote WMS layers 226 Layer layer = configuration.getLayer( request.getLayer() ); 227 if ( layer != null && layer.getDataSource() != null && layer.getDataSource().length > 0 ) { 228 AbstractDataSource ds = layer.getDataSource()[0]; 229 if ( ds.getType() == AbstractDataSource.REMOTEWMS ) { 230 Object o = ( (RemoteWMSDataSource) ds ).getOGCWebService().doService( request ); 231 if ( o instanceof GetLegendGraphicResult ) { 232 OGCWebServiceException exc = ( (GetLegendGraphicResult) o ).getException(); 233 if ( exc != null ) { 234 throw exc; 235 } 236 le = new LegendFactory().createLegendElement( (BufferedImage) ( (GetLegendGraphicResult) o ).getLegendGraphic() ); 237 } 238 } else if ( ds.getType() == AbstractDataSource.EXTERNALDATAACCESS ) { 239 ExternalDataAccess eda = ( (ExternalDataAccessDataSource) ds ).getExternalDataAccess(); 240 le = new LegendFactory().createLegendElement( eda.perform( request ) ); 241 } 242 } 243 244 if ( le == null ) { 245 le = getFromWellKnownStyle(); 246 } 247 } else { 248 le = getFromSLDStyle(); 249 } 250 } catch ( Exception e ) { 251 LOG.logError( e.getMessage(), e ); 252 String s = Messages.getMessage( "WMS_LEGENDELEM" ); 253 throw new OGCWebServiceException( getClass().getName(), s ); 254 } 255 256 return le; 257 } 258 259 /** 260 * creates a LegendElement from a style known by the WMS 261 */ 262 private LegendElement getFromWellKnownStyle() 263 throws OGCWebServiceException { 264 265 String layerName = request.getLayer(); 266 String styleName = request.getStyle(); 267 LegendElement le = null; 268 LegendFactory lf = new LegendFactory(); 269 270 try { 271 // get Layer object from the WMS capabilities 272 Layer layer = configuration.getLayer( layerName ); 273 // get the Style section from the matching the requested style 274 org.deegree.ogcwebservices.wms.capabilities.Style nStyle = getNamedStyle( styleName ); 275 LegendURL[] lURLs = nStyle.getLegendURL(); 276 OperationsMetadata om = configuration.getOperationMetadata(); 277 Operation op = om.getOperation( new QualifiedName( "GetLegendGraphic" ) ); 278 URL url = null; 279 if ( op != null ) { 280 // TODO 281 // should check if really HTTP 282 List<DCP> dcpList = op.getDCP(); 283 HTTP http = (HTTP) dcpList.get( 0 ); 284 url = http.getLinks().get( 0 ).getLinkage().getHref(); 285 if ( lURLs[0].getOnlineResource().getHost().equals( url.getHost() ) 286 && lURLs[0].getOnlineResource().toExternalForm().indexOf( "GetLegendGraphic" ) > -1 ) { 287 String s = StringTools.concat( 200, "GetLegendGraphic request ", 288 "to the WMS itself has been set has defined ", 289 "as LegendURL for layer: ", layerName ); 290 LOG.logInfo( s ); 291 // avoid cyclic calling of WMS 292 UserStyle style = layer.getStyle( styleName ); 293 if ( style != null ) { 294 // drawing legend symbol 295 String title = configuration.getLayer( layerName ).getTitle(); 296 le = lf.createLegendElement( style, request.getWidth(), request.getHeight(), title ); 297 } else { 298 s = Messages.getMessage( "WMS_GENERALSTYLEERROR", styleName ); 299 throw new OGCWebServiceException( getClass().getName(), s ); 300 } 301 } else { 302 // if a legend url is defined will be used for creating the legend 303 // symbol; otherwise it will be tried to create the legend symbol 304 // dynamicly 305 try { 306 BufferedImage bi = ImageUtils.loadImage( lURLs[0].getOnlineResource() ); 307 le = lf.createLegendElement( bi ); 308 } catch ( Exception e ) { 309 String s = StringTools.concat( 200, "can not open legen URL: ", lURLs[0].getOnlineResource(), 310 "; try to create ", "legend symbol dynamicly." ); 311 LOG.logInfo( s ); 312 UserStyle style = layer.getStyle( styleName ); 313 if ( style != null ) { 314 // drawing legend symbol 315 String title = configuration.getLayer( layerName ).getTitle(); 316 le = lf.createLegendElement( style, request.getWidth(), request.getHeight(), title ); 317 } else { 318 s = Messages.getMessage( "WMS_GENERALSTYLEERROR", styleName ); 319 throw new OGCWebServiceException( getClass().getName(), s ); 320 } 321 } 322 323 } 324 } 325 326 } catch ( Exception e ) { 327 LOG.logError( e.getMessage(), e ); 328 throw new OGCWebServiceException( e.getMessage() ); 329 } 330 return le; 331 } 332 333 /** 334 * creates a LegendElement from a style defined in the SLD document passed/referenced by/in the request 335 */ 336 private LegendElement getFromSLDStyle() 337 throws OGCWebServiceException { 338 339 String layerName = request.getLayer(); 340 String styleName = request.getStyle(); 341 LegendElement le = null; 342 LegendFactory lf = new LegendFactory(); 343 344 try { 345 org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers(); 346 for ( int i = 0; i < sldLayers.length; i++ ) { 347 if ( layerName.equals( sldLayers[i].getName() ) ) { 348 org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles(); 349 org.deegree.graphics.sld.AbstractStyle style = null; 350 if ( styleName == null ) { 351 style = sldStyles[0]; 352 } else { 353 for ( int k = 0; k < sldStyles.length; k++ ) { 354 if ( sldStyles[k].getName().equals( styleName ) ) { 355 style = sldStyles[k]; 356 break; 357 } 358 } 359 } 360 String title = configuration.getLayer( layerName ).getTitle(); 361 le = lf.createLegendElement( style, request.getWidth(), request.getHeight(), title ); 362 } 363 } 364 } catch ( Exception e ) { 365 LOG.logError( e.getMessage(), e ); 366 throw new OGCWebServiceException( StringTools.stackTraceToString( e.getStackTrace() ) ); 367 } 368 369 return le; 370 } 371 372 }