001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/wms/control/DynLegendListener.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.portal.standard.wms.control; 037 038 import static org.deegree.enterprise.WebUtils.enableProxyUsage; 039 040 import java.awt.Color; 041 import java.awt.Graphics; 042 import java.awt.Rectangle; 043 import java.awt.geom.Rectangle2D; 044 import java.awt.image.BufferedImage; 045 import java.io.File; 046 import java.io.FileOutputStream; 047 import java.io.IOException; 048 import java.io.InputStreamReader; 049 import java.net.MalformedURLException; 050 import java.net.URL; 051 import java.util.ArrayList; 052 import java.util.HashMap; 053 import java.util.List; 054 import java.util.Map; 055 import java.util.Properties; 056 import java.util.StringTokenizer; 057 058 import javax.servlet.http.HttpServletRequest; 059 import javax.servlet.http.HttpSession; 060 061 import org.apache.commons.httpclient.HttpClient; 062 import org.apache.commons.httpclient.methods.GetMethod; 063 import org.deegree.datatypes.QualifiedName; 064 import org.deegree.enterprise.control.FormEvent; 065 import org.deegree.enterprise.control.RPCMember; 066 import org.deegree.enterprise.control.RPCMethodCall; 067 import org.deegree.enterprise.control.RPCParameter; 068 import org.deegree.enterprise.control.RPCStruct; 069 import org.deegree.enterprise.control.RPCWebEvent; 070 import org.deegree.framework.log.ILogger; 071 import org.deegree.framework.log.LoggerFactory; 072 import org.deegree.framework.util.IDGenerator; 073 import org.deegree.framework.util.ImageUtils; 074 import org.deegree.framework.util.StringTools; 075 import org.deegree.framework.xml.XMLFragment; 076 import org.deegree.ogcbase.ImageURL; 077 import org.deegree.ogcwebservices.InconsistentRequestException; 078 import org.deegree.ogcwebservices.wms.capabilities.LegendURL; 079 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 080 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 081 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 082 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic; 083 import org.deegree.owscommon_new.HTTP; 084 import org.deegree.owscommon_new.Operation; 085 import org.deegree.portal.Constants; 086 import org.deegree.portal.context.GeneralExtension; 087 import org.deegree.portal.context.IOSettings; 088 import org.deegree.portal.context.Layer; 089 import org.deegree.portal.context.LayerList; 090 import org.deegree.portal.context.ViewContext; 091 092 /** 093 * Will be called if the client forces a dynamic legend. There are two different ways of retreiving the legend for each 094 * layer: 095 * 096 * First, we try to get the legend from the layer information in the WMC. 097 * 098 * Second, we try to get the legend from the WMS serving this layer: It is attempted to get the legend url from style 099 * info in the WMS Capabilities, first with the passed style info, second for the default style, third for the only 100 * available style. (If the WMS capabilities holds more than one style, but no style was passed with the layer info, 101 * then one cannot know "the right style". Therefore no style is taken from WMS capabilities, in this case.) Then, it is 102 * attempted to get the legend image from a GetLegendGraphics request, if the WMS capabilities state, that this request 103 * is supported by the WMS. 104 * 105 * If this all fails, the missingImage is taken if defined in init params. 106 * 107 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 108 * @author last edited by: $Author: mays$ 109 * 110 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 111 */ 112 public class DynLegendListener extends AbstractMapListener { 113 114 private static final ILogger LOG = LoggerFactory.getLogger( DynLegendListener.class ); 115 116 private int leftMargin = 15; 117 118 private int rightMargin = 15; 119 120 private int topMargin = 20; 121 122 private int bottomMargin = 20; 123 124 private boolean useLayerTitle = true; 125 126 private BufferedImage separator; 127 128 private BufferedImage missingImg; 129 130 private static Map<String, Object> wmscache = new HashMap<String, Object>(); 131 132 private static Map<String, BufferedImage> legendSymCache = new HashMap<String, BufferedImage>(); 133 134 private List<String> missing = null; 135 136 private int maxNNLegendSize = 50; 137 138 private Properties userNames = new Properties(); 139 140 private Properties passwords = new Properties(); 141 142 /* 143 * (non-Javadoc) 144 * 145 * @see org.deegree.portal.standard.wms.control.AbstractMapListener#actionPerformed(org.deegree.enterprise.control.FormEvent) 146 */ 147 @Override 148 public void actionPerformed( FormEvent event ) { 149 150 super.actionPerformed( event ); 151 missing = new ArrayList<String>(); 152 153 try { 154 init(); 155 } catch ( IOException e ) { 156 LOG.logError( "DynLegendListener: Error occurred initializing DynLegendListener: ", e ); 157 gotoErrorPage( "Error occurred initializing DynLegendListener: " + e ); 158 } 159 160 RPCWebEvent rpc = (RPCWebEvent) event; 161 RPCMethodCall mc = rpc.getRPCMethodCall(); 162 RPCParameter[] para = mc.getParameters(); 163 RPCStruct struct = (RPCStruct) para[0].getValue(); 164 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession(); 165 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); 166 HashMap[] model = createWMSRequestModel( struct ); 167 168 try { 169 GetLegendGraphic legendParam = getLegendRequestParameter(); 170 HashMap<String, Object> symbols = (HashMap<String, Object>) readLegendSymbols( legendParam, model, vc ); 171 Rectangle rect = calcLegendSize( symbols ); 172 BufferedImage bi = new BufferedImage( rect.width + leftMargin + rightMargin, rect.height + topMargin 173 + bottomMargin, 174 BufferedImage.TYPE_INT_RGB ); 175 Color color = Color.decode( (String) struct.getMember( "bgColor" ).getValue() ); 176 bi = drawSymbolsToBI( symbols, bi, color ); 177 saveImage( vc, bi ); 178 179 getRequest().setAttribute( "LEGENDWIDTH", String.valueOf( bi.getWidth() ) ); 180 getRequest().setAttribute( "LEGENDHEIGHT", String.valueOf( bi.getHeight() ) ); 181 } catch ( Exception e ) { 182 LOG.logError( "DynLegendListener: Error occurred in DynLegendListener: ", e ); 183 gotoErrorPage( "Error occurred in DynLegendListener: " + e ); 184 } 185 186 } 187 188 /** 189 * Reads the initParams from the controller.xml and assigns them to the global variables 190 * 191 * @throws IOException 192 */ 193 private void init() 194 throws IOException { 195 String path = null; 196 197 String tmp = getInitParameter( "leftMargin" ); 198 if ( tmp != null ) { 199 leftMargin = Integer.parseInt( tmp ); 200 } 201 tmp = getInitParameter( "rightMargin" ); 202 if ( tmp != null ) { 203 rightMargin = Integer.parseInt( tmp ); 204 } 205 tmp = getInitParameter( "topMargin" ); 206 if ( tmp != null ) { 207 topMargin = Integer.parseInt( tmp ); 208 } 209 tmp = getInitParameter( "bottomMargin" ); 210 if ( tmp != null ) { 211 bottomMargin = Integer.parseInt( tmp ); 212 } 213 tmp = getInitParameter( "useLayerTitle" ); 214 useLayerTitle = "true".equalsIgnoreCase( tmp ); 215 216 tmp = getInitParameter( "separator" ); 217 if ( tmp != null ) { 218 path = StringTools.concat( 200, getHomePath(), tmp ); 219 LOG.logDebug( "PATH = ", path ); 220 separator = ImageUtils.loadImage( path ); 221 } 222 223 tmp = getInitParameter( "missingImage" ); 224 if ( tmp != null ) { 225 path = StringTools.concat( 200, getHomePath(), tmp ); 226 LOG.logDebug( "PATH = ", path ); 227 try { 228 missingImg = ImageUtils.loadImage( path ); 229 } catch ( Exception e ) { 230 LOG.logError( e.getLocalizedMessage() ); 231 missingImg = new BufferedImage( 10, 10, BufferedImage.TYPE_INT_ARGB ); 232 } 233 } else { 234 missingImg = new BufferedImage( 10, 10, BufferedImage.TYPE_INT_ARGB ); 235 } 236 tmp = getInitParameter( "maxNNLegendSize" ); 237 if ( tmp != null ) { 238 maxNNLegendSize = Integer.parseInt( tmp ); 239 } 240 tmp = getInitParameter( "users" ); 241 if ( tmp != null ) { 242 String[] t = StringTools.toArray( tmp, ";|", false ); 243 for ( int i = 0; i < t.length; i += 3 ) { 244 userNames.put( t[i], t[i + 1] ); 245 passwords.put( t[i], t[i + 2] ); 246 } 247 } 248 } 249 250 /** 251 * takes in a HashMap holding the properties of the legend and returns the size of the legend to be 252 * 253 * @param map 254 * Hashmap holding the GetLegendGraphic properties 255 * @return A rectangle holding the legend size 256 */ 257 private Rectangle calcLegendSize( HashMap map ) { 258 259 String[] layers = (String[]) map.get( "NAMES" ); 260 String[] titles = (String[]) map.get( "TITLES" ); 261 BufferedImage[] legs = (BufferedImage[]) map.get( "IMAGES" ); 262 263 int w = 0; 264 int h = 0; 265 for ( int i = 0; i < layers.length; i++ ) { 266 h += legs[i].getHeight() + 5; 267 if ( separator != null && i < layers.length - 1 ) { 268 h += separator.getHeight() + 5; 269 } 270 Graphics g = legs[i].getGraphics(); 271 if ( useLayerTitle && legs[i].getHeight() < maxNNLegendSize && !missing.contains( layers[i] ) ) { 272 Rectangle2D rect = g.getFontMetrics().getStringBounds( titles[i], g ); 273 g.dispose(); 274 if ( ( rect.getWidth() + legs[i].getWidth() ) > w ) { 275 w = (int) rect.getWidth() + legs[i].getWidth(); 276 } 277 } else { 278 if ( legs[i].getWidth() > w ) { 279 w = legs[i].getWidth(); 280 } 281 } 282 } 283 // w += 20; 284 285 return new Rectangle( w, h ); 286 } 287 288 /** 289 * Draws the given symbol to the given image 290 * 291 * @param map 292 * Hashmap holding the properties of the legend 293 * @param bi 294 * image of the legend 295 * @param color 296 * color to fill the graphic 297 * @return The drawn BufferedImage 298 */ 299 private BufferedImage drawSymbolsToBI( HashMap map, BufferedImage bi, Color color ) { 300 301 Graphics g = bi.getGraphics(); 302 g.setColor( color ); 303 g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() ); 304 305 String[] layers = (String[]) map.get( "NAMES" ); 306 String[] titles = (String[]) map.get( "TITLES" ); 307 BufferedImage[] legs = (BufferedImage[]) map.get( "IMAGES" ); 308 int h = topMargin; 309 for ( int i = layers.length - 1; i >= 0; i-- ) { 310 g.drawImage( legs[i], leftMargin, h, null ); 311 g.setColor( Color.BLACK ); 312 // just draw title if the flag has been set in listener configuration, 313 // the legend image is less than a defined value and a legend image 314 // (not missing) has been accessed 315 if ( useLayerTitle && legs[i].getHeight() < maxNNLegendSize && !missing.contains( layers[i] ) ) { 316 g.drawString( titles[i], leftMargin + legs[i].getWidth() + 10, h + (int) ( legs[i].getHeight() / 1.2 ) ); 317 } 318 h += legs[i].getHeight() + 5; 319 if ( separator != null && i > 0 ) { 320 g.drawImage( separator, leftMargin, h, null ); 321 h += separator.getHeight() + 5; 322 } 323 } 324 g.dispose(); 325 return bi; 326 } 327 328 /** 329 * Receives an RPCStruct(WMSRequest) and extracts all its properties to a HashMap 330 * 331 * @param struct 332 * @return a HashMap contains the WMSRequest properties 333 */ 334 private HashMap[] createWMSRequestModel( RPCStruct struct ) { 335 336 RPCMember[] member = struct.getMembers(); 337 String request = ""; 338 List<Map<String, String>> list = new ArrayList<Map<String, String>>( member.length - 1 ); 339 for ( int i = 0; i < member.length; i++ ) { 340 if ( !member[i].getName().equals( "bgColor" ) && !member[i].getName().equals( "sessionID" ) ) { 341 request = (String) member[i].getValue(); 342 LOG.logDebug( "*** request = " + request ); 343 Map<String, String> map = toMap( request ); 344 StringTokenizer st = new StringTokenizer( request, "?" ); 345 map.put( "URL", st.nextToken() ); 346 list.add( map ); 347 } 348 } 349 HashMap[] getMR = new HashMap[list.size()]; 350 return list.toArray( getMR ); 351 } 352 353 /** 354 * Saves the given image to the print/images directory of the given ViewContext 355 * 356 * @param vc 357 * @param bg 358 */ 359 private void saveImage( ViewContext vc, BufferedImage bg ) { 360 361 GeneralExtension ge = vc.getGeneral().getExtension(); 362 IOSettings ios = ge.getIOSettings(); 363 String dir = ios.getPrintDirectory().getDirectoryName(); 364 String format = "png"; 365 long l = IDGenerator.getInstance().generateUniqueID(); 366 String file = StringTools.concat( 50, "legend", l, ".", format ); 367 int pos = dir.lastIndexOf( '/' ); 368 String access = StringTools.concat( 100, "./", dir.substring( pos + 1, dir.length() ), "/", file ); 369 370 String temp = StringTools.concat( 100, "legend", ( l - 50 ), ".", format ); 371 File f = new File( StringTools.concat( 100, "./", dir.substring( pos + 1, dir.length() ), "/", temp ) ); 372 try { 373 if ( f.exists() ) { 374 f.delete(); 375 } 376 } catch ( Exception e ) { 377 if ( LOG.getLevel() == ILogger.LOG_ERROR ) { 378 LOG.logError( StringTools.concat( 100, "DynLegendListener: The temporary image file: ", f.getPath(), 379 " could not be deleted" ) ); 380 } 381 } 382 try { 383 String path = new String( StringTools.concat( 100, dir, "/", file ) ); 384 if ( path.startsWith( "file:/" ) ) { 385 path = new URL( path ).getFile(); 386 } 387 FileOutputStream fos = new FileOutputStream( new File( path ) ); 388 ImageUtils.saveImage( bg, fos, format, 1 ); 389 fos.close(); 390 391 } catch ( Exception e ) { 392 LOG.logError( "DynLegendListener: Error occurred in saving legend image: ", e ); 393 } 394 this.getRequest().setAttribute( "LEGENDURL", access ); 395 396 } 397 398 /** 399 * Creates a GetLegendGraphic Request 400 * 401 * @return An instance of GetLegendGraphic 402 * @throws InconsistentRequestException 403 */ 404 private GetLegendGraphic getLegendRequestParameter() 405 throws InconsistentRequestException { 406 407 HashMap<String, String> legend = toMap( "VERSION=1.1.1&REQUEST=GetLegendGraphic&FORMAT=image/png&WIDTH=50&HEIGHT=50&" 408 + "EXCEPTIONS=application/vnd.ogc.se_inimage&LAYER=europe:major_rivers&STYLE=default" ); 409 410 GetLegendGraphic legendReq = GetLegendGraphic.create( legend ); 411 412 return legendReq; 413 } 414 415 /** 416 * Creates legend symbols and stores them in a hashmap through the given params 417 * 418 * There are two different ways of retreiving the legend. First, we try to get the legend from the layer information 419 * in the WMC. Second, we try to get the legend from the WMS serving this layer. 420 * 421 * If both fails, the missingImage as defined in init params is taken. 422 * 423 * @param glr 424 * @param model 425 * A HashMap holding the Request params (with URL holding the service address itself) 426 * @param vc 427 * Current layer list 428 * @return A HashMap holding the legend symbols as read from the cash 429 * @throws IOException 430 */ 431 private Map<String, Object> readLegendSymbols( GetLegendGraphic glr, HashMap[] model, ViewContext vc ) 432 throws IOException { 433 434 ArrayList<String> list1 = new ArrayList<String>(); 435 ArrayList<BufferedImage> list2 = new ArrayList<BufferedImage>(); 436 ArrayList<String> list3 = new ArrayList<String>(); 437 438 LayerList ll = vc.getLayerList(); 439 440 StringTokenizer st = null; 441 String format = glr.getFormat(); 442 if ( format.equals( "image/jpg" ) ) { 443 format = "image/jpeg"; 444 } 445 446 int lgHeight = 0; 447 for ( int i = 0; i < model.length; i++ ) { 448 if ( model[i].get( "LAYERS" ) != null ) { 449 String style = (String) model[i].get( "STYLES" ); 450 String[] styles = new String[100]; 451 if ( style != null ) { 452 styles = StringTools.toArray( style, ",", false ); 453 } 454 455 // read capabilities for current service (URL) or - if avalable - 456 // read it from the cache 457 String addr = (String) model[i].get( "URL" ); 458 if ( wmscache.get( addr ) == null ) { 459 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 460 LOG.logDebug( StringTools.concat( 200, "DynLegendListener: Adding the caps of ", addr, 461 " to the hash map" ) ); 462 } 463 wmscache.put( addr, getCapabilities( addr, (String) model[i].get( "VERSION" ) ) ); 464 } else { 465 LOG.logDebug( "DynLegendListener: read capabilities from cache" ); 466 467 } 468 LOG.logDebug( "DynLegendListener: caps ", addr ); 469 WMSCapabilities capa = (WMSCapabilities) wmscache.get( addr ); 470 471 st = new StringTokenizer( (String) model[i].get( "LAYERS" ), "," ); 472 int k = 0; 473 while ( st.hasMoreTokens() ) { 474 if ( styles == null || styles.length == 0 || styles[k] == null || styles[k].equals( "" ) ) { 475 style = "default"; 476 } else { 477 style = styles[k]; 478 } 479 k++; 480 481 String layer = st.nextToken(); 482 String title = layer; 483 if ( capa.getLayer( layer ) != null ) { 484 title = capa.getLayer( layer ).getTitle(); 485 } 486 487 BufferedImage legendGraphic = null; 488 String path = StringTools.concat( 200, addr, "%%", layer, "%%", style ); 489 if ( legendSymCache.get( path ) != null ) { 490 legendGraphic = legendSymCache.get( path ); 491 LOG.logDebug( "DynLegendListener: read legendsymbol from cache for ", layer ); 492 } else { 493 // first attempt to get legend image: access layer from WMC. 494 // (If current WMC does not offer a layer named like the passed name, the layer 495 // may have been added dynamically => see second attempt further below.) 496 LOG.logDebug( "legendURL for layer", layer, " from ", addr ); 497 Layer lay = ll.getLayer( layer, addr ); 498 if ( lay == null ) { 499 LOG.logWarning( "layer '" + layer + "' not found in layer list" ); 500 } 501 ImageURL imgUrl = null; 502 URL url = null; 503 if ( lay != null && lay.getStyleList() != null && lay.getStyleList().getStyle( style ) != null 504 && ( imgUrl = lay.getStyleList().getStyle( style ).getLegendURL() ) != null ) { 505 LOG.logDebug( "An image url could be fetched from WMC" ); 506 url = imgUrl.getOnlineResource(); 507 } else { 508 LOG.logDebug( "No url found from WMC for layer ", layer ); 509 } 510 511 lgHeight = lgHeight + 30; 512 513 if ( url != null ) { 514 LOG.logDebug( "DynLegendListener: URL is valid. Loading Legend Graphic..." ); 515 LOG.logDebug( "ImgUrl is: ", url.toExternalForm() ); 516 // TODO catch error from loadImage, but also log the error message. 517 // error might occure, if configuration is wrong. 518 // (trying to read from a not existing feature) 519 try { 520 legendGraphic = ImageUtils.loadImage( url ); 521 } catch ( Exception e ) { 522 // nothing to do 523 } 524 } 525 526 // second attempt to get legend image: necessary if layer has been added dynamically. 527 if ( legendGraphic == null ) { 528 LOG.logDebug( "SECOND ATTEMPT for the legend image, because layer was not in WMC LayerList" ); 529 legendGraphic = createLegendSybmbol( (WMSCapabilities) wmscache.get( addr ), layer, style ); 530 } 531 532 // store legend in cache 533 legendSymCache.put( path, legendGraphic ); 534 } 535 list1.add( layer ); 536 list2.add( legendGraphic ); 537 list3.add( title ); 538 } 539 } 540 } 541 542 String[] layers = list1.toArray( new String[list1.size()] ); 543 BufferedImage[] legs = list2.toArray( new BufferedImage[list2.size()] ); 544 String[] titles = list3.toArray( new String[list3.size()] ); 545 Map<String, Object> map = new HashMap<String, Object>(); 546 map.put( "NAMES", layers ); 547 map.put( "TITLES", titles ); 548 map.put( "IMAGES", legs ); 549 550 return map; 551 } 552 553 /** 554 * This method is called, when no legend image could be retreived from the information given in the WebMapContext 555 * document. The layer was probably added during runtime dynamically. 556 * 557 * It is attempted to get the legend url from style info in the WMS Capabilities, first with the passed style info, 558 * second for the default style, third for the only available style. (If the WMS capabilities holds more than one 559 * style, but no style was passed with the layer info, then one cannot know "the right style". Therefore no style is 560 * taken from WMS capabilities, in this case.) 561 * 562 * Then, it is attempted to get the legend image from a GetLegendGraphics request, if the WMS capabilities state, 563 * that this request is supported by the WMS. 564 * 565 * If all this fails, the image is taken from init param "missingImage". 566 * 567 * @param wmsCapa 568 * @param layer 569 * @param style 570 * @return the legend image or the missingImage 571 */ 572 private BufferedImage createLegendSybmbol( WMSCapabilities wmsCapa, String layer, String style ) { 573 574 URL url = null; 575 org.deegree.ogcwebservices.wms.capabilities.Layer ogcLayer = wmsCapa.getLayer( layer ); 576 577 try { 578 if ( style == null ) { 579 style = "default"; 580 } 581 582 // 1. get style for layer 583 // first try with "default" and then with "" (empty string) as style name 584 org.deegree.ogcwebservices.wms.capabilities.Style ogcStyle = ogcLayer.getStyleResource( style ); 585 if ( ogcStyle == null ) { 586 ogcStyle = ogcLayer.getStyleResource( "" ); 587 } 588 // try to get another style for layer (only, if there is just one style definition) 589 if ( ogcStyle == null ) { 590 LOG.logDebug( "Layer ", layer, " has no valid default style definition." ); 591 org.deegree.ogcwebservices.wms.capabilities.Style[] styles = ogcLayer.getStyles(); 592 if ( styles.length == 1 ) { 593 // using the only available style definition as default style definition 594 LOG.logDebug( "Layer ", layer, " has only one style definition. Assuming this as default style." ); 595 ogcStyle = styles[0]; 596 } else { 597 // more than one style definition available, but non is the default style. 598 // Therefore no style definition can be chosen. Nothing happens here. 599 } 600 } 601 602 // 2. try to get legend url from style definition 603 if ( ogcStyle != null ) { 604 LegendURL[] legendUrls = ogcStyle.getLegendURL(); 605 if ( legendUrls != null && legendUrls.length > 0 ) { 606 // First field of the array contains a url to the legend 607 LOG.logDebug( "Obtaining legend url from the OGCStyle for layer: ", layer ); 608 url = legendUrls[0].getOnlineResource(); 609 } 610 } 611 612 // 3. try to get legend url from getLegendGraphic request 613 if ( ogcStyle == null || url == null ) { 614 // either layer does not have a style info at all 615 // or layer has a style info, but this style does not contain a legend url 616 QualifiedName name = new QualifiedName( "GetLegendGraphic" ); 617 Operation op = wmsCapa.getOperationMetadata().getOperation( name ); 618 LOG.logDebug( "Obtaining the legend graphic from the metadata of the wms for layer: ", layer ); 619 if ( op != null ) { 620 HTTP http = (HTTP) op.getDCP().get( 0 ); 621 url = http.getGetOnlineResources().get( 0 ); 622 LOG.logDebug( "legend url obtained from operation metadata" ); 623 } else { 624 LOG.logDebug( "GetLegendGrpahic not served by the service." ); 625 } 626 LOG.logDebug( "LegendURLs can not be extracted from ogcStyle." ); 627 } 628 } catch ( Exception e ) { 629 LOG.logError( e.getLocalizedMessage() ); 630 } 631 632 if ( url == null ) { 633 return createMissingLegend( ogcLayer.getTitle() ); 634 } else { 635 try { 636 return ImageUtils.loadImage( url ); 637 } catch ( Exception e ) { 638 LOG.logError( e.getLocalizedMessage() ); 639 return createMissingLegend( ogcLayer.getTitle() ); 640 } 641 } 642 } 643 644 /** 645 * In case the legend can not be obtained from the OGCLayer, this method is called to create a dummy legend image 646 * plus the legend title 647 * 648 * @param layerName 649 * @return BufferedImage holding the created dummy legend 650 */ 651 private BufferedImage createMissingLegend( String layerName ) { 652 LOG.logDebug( "URL is null. Drawing the image from a missingImage variable in init params" ); 653 BufferedImage missingLegend = new BufferedImage( 80, 15, BufferedImage.TYPE_INT_RGB ); 654 Graphics g = missingLegend.getGraphics(); 655 Rectangle2D rect = g.getFontMetrics().getStringBounds( layerName, g ); 656 g.dispose(); 657 missingLegend = new BufferedImage( rect.getBounds().width + 80, missingImg.getHeight() + 15, 658 BufferedImage.TYPE_INT_ARGB ); 659 g = missingLegend.getGraphics(); 660 g.drawImage( missingImg, 0, 0, null ); 661 g.setColor( Color.RED ); 662 if ( useLayerTitle ) { 663 g.drawString( layerName, missingImg.getWidth() + 5, missingImg.getHeight() / 2 + g.getFont().getSize() / 2 ); 664 } 665 g.dispose(); 666 667 return missingLegend; 668 } 669 670 /** 671 * Performs a GetCapabilities request (now also with proxy usage enabled) 672 * 673 * @param url 674 * @param version 675 * @return the obtained WMSCapbilities 676 */ 677 private WMSCapabilities getCapabilities( String url, String version ) { 678 679 WMSCapabilities capa = null; 680 HttpClient httpclient = new HttpClient(); 681 try { 682 enableProxyUsage( httpclient, new URL( url ) ); 683 } catch ( MalformedURLException e ) { 684 LOG.logError( "the passed url was not well formed.", e ); 685 } 686 687 httpclient.getHttpConnectionManager().getParams().setSoTimeout( 15000 ); 688 StringBuffer sb = new StringBuffer( 500 ); 689 sb.append( url ); 690 sb.append( "?request=GetCapabilities&service=WMS&version=" ); 691 sb.append( version ); 692 693 if ( userNames.get( url ) != null ) { 694 sb.append( "&USER=" ).append( userNames.get( url ) ); 695 sb.append( "&PASSWORD=" ); 696 if ( passwords.get( url ) != null ) { 697 sb.append( passwords.get( url ) ); 698 } 699 } 700 LOG.logDebug( sb.toString() ); 701 GetMethod httpget = new GetMethod( sb.toString() ); 702 try { 703 httpclient.executeMethod( httpget ); 704 XMLFragment xml = new XMLFragment(); 705 xml.load( new InputStreamReader( httpget.getResponseBodyAsStream() ), XMLFragment.DEFAULT_URL ); 706 WMSCapabilitiesDocument cdoc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( xml.getRootElement() ); 707 capa = (WMSCapabilities) cdoc.parseCapabilities(); 708 } catch ( Exception e ) { 709 LOG.logError( "GetCaps failed for " + sb.toString() ); 710 } 711 return capa; 712 } 713 }