001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/wms/control/PrintListener.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 java.awt.Color;
039    import java.awt.Font;
040    import java.awt.Graphics;
041    import java.awt.Rectangle;
042    import java.awt.geom.Rectangle2D;
043    import java.awt.image.BufferedImage;
044    import java.io.File;
045    import java.io.FileOutputStream;
046    import java.io.IOException;
047    import java.io.InputStream;
048    import java.io.UnsupportedEncodingException;
049    import java.net.MalformedURLException;
050    import java.net.URL;
051    import java.net.URLDecoder;
052    import java.util.ArrayList;
053    import java.util.HashMap;
054    import java.util.StringTokenizer;
055    
056    import javax.imageio.ImageIO;
057    import javax.servlet.http.HttpServletRequest;
058    import javax.servlet.http.HttpSession;
059    
060    import org.deegree.enterprise.control.FormEvent;
061    import org.deegree.enterprise.control.RPCMember;
062    import org.deegree.enterprise.control.RPCMethodCall;
063    import org.deegree.enterprise.control.RPCParameter;
064    import org.deegree.enterprise.control.RPCStruct;
065    import org.deegree.enterprise.control.RPCWebEvent;
066    import org.deegree.framework.log.ILogger;
067    import org.deegree.framework.log.LoggerFactory;
068    import org.deegree.framework.util.CharsetUtils;
069    import org.deegree.framework.util.IDGenerator;
070    import org.deegree.framework.util.ImageUtils;
071    import org.deegree.framework.util.StringTools;
072    import org.deegree.framework.xml.XMLParsingException;
073    import org.deegree.model.crs.UnknownCRSException;
074    import org.deegree.ogcwebservices.InconsistentRequestException;
075    import org.deegree.ogcwebservices.OGCWebServiceException;
076    import org.deegree.ogcwebservices.OWSUtils;
077    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
078    import org.deegree.ogcwebservices.wms.operation.GetMap;
079    import org.deegree.portal.Constants;
080    import org.deegree.portal.context.GeneralExtension;
081    import org.deegree.portal.context.IOSettings;
082    import org.deegree.portal.context.ViewContext;
083    
084    /**
085     * will be called if the client forces a print action.
086     *
087     * @deprecated use @see org.deegree.portal.common.control.AbstractSimplePrintListener
088     *
089     * @author <a href="mailto:lupp@lat-lon.de">Katharina Lupp</a>
090     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
091     * @author last edited by: $Author: mschneider $
092     *
093     * @version $Revision: 18195 $ $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
094     */
095    @Deprecated
096    public class PrintListener extends AbstractMapListener {
097    
098        private static final ILogger LOG = LoggerFactory.getLogger( PrintListener.class );
099    
100        /*
101         * the method will be called if a print action/event occurs.
102         *
103         * (non-Javadoc)
104         * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent)
105         */
106        @Override
107        public void actionPerformed( FormEvent event ) {
108    
109            super.actionPerformed( event );
110    
111            RPCWebEvent rpc = (RPCWebEvent) event;
112            RPCMethodCall mc = rpc.getRPCMethodCall();
113            RPCParameter[] para = mc.getParameters();
114            RPCStruct struct = (RPCStruct) para[0].getValue(); // paperFormat, resolution, orientation, format
115            RPCStruct struct2 = (RPCStruct) para[1].getValue(); // wmsRequest_0 .. wmsRequest_i
116    
117            HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true );
118            ViewContext vc = null;
119            if ( session.getAttribute( Constants.CURRENTMAPCONTEXT ) != null ) {
120                vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT );
121            } else {
122                vc = (ViewContext) session.getAttribute( "DefaultMapContext" );
123            }
124    
125            HashMap[] model = createWMSRequestModel( struct2 );
126            int[] imageSize = calcImageSize( struct, model[0] );
127            int width = imageSize[0];
128            //int height = imageSize[1];
129            int xmap = imageSize[2];
130            int ymap = imageSize[3];
131            int mapStart = imageSize[4];
132    
133            try {
134                GetLegendGraphic legendParam = getLegendRequestParameter();
135                //HashMap with legend
136                HashMap symbols = getLegend( struct, legendParam, model );
137                Rectangle rectLegend = calcLegendSize( struct, symbols );
138                Rectangle rectMap = calcMapSize( model, rectLegend, width );
139                //sets new size of map und creates the adequate BufferedImage
140                model = modifyModelSize( rectMap, model, xmap, ymap );
141                HashMap[] copy = createCopy( model );
142                BufferedImage biReq = getMap( copy );
143    
144                //creates BufferedImage with required size and creates graphic
145                BufferedImage bi = createBackgroundImage( rectMap, rectLegend );
146    
147                bi = drawMapToBI( biReq, bi, mapStart );
148                bi = drawLegendToBI( symbols, bi, ( mapStart + rectMap.width ) );
149    
150                saveImage( vc, struct, bi );
151    
152            } catch ( Exception e ) {
153                e.printStackTrace();
154            }
155    
156        }
157    
158        /**
159         * creates a background BufferedImage for the attributes (map, legend, scalebar)
160         *
161         * @param rectMap
162         * @param rectLegend
163         * @return
164         */
165        private BufferedImage createBackgroundImage( Rectangle rectMap, Rectangle rectLegend ) {
166            BufferedImage bi = null;
167    
168            if ( rectMap.height > rectLegend.height ) {
169                bi = new BufferedImage( rectMap.width + rectLegend.width + 40, rectMap.height + 100,
170                                        BufferedImage.TYPE_INT_RGB );
171            } else {
172                bi = new BufferedImage( rectMap.width + rectLegend.width + 40, rectLegend.height + 100,
173                                        BufferedImage.TYPE_INT_RGB );
174            }
175    
176            Graphics g = bi.getGraphics();
177            g.setColor( Color.WHITE );
178            g.fillRect( 1, 1, bi.getWidth() - 2, bi.getHeight() - 2 );
179            g.dispose();
180    
181            return bi;
182        }
183    
184        /**
185         * creates copy of the model
186         *
187         * @param model
188         * @return the copy of the model
189         */
190        private HashMap[] createCopy( HashMap[] model ) {
191            HashMap[] copy = new HashMap[model.length];
192            synchronized ( this ) {
193                for ( int i = 0; i < model.length; i++ ) {
194                    copy[i] = (HashMap) model[i].clone();
195                }
196            }
197    
198            return copy;
199        }
200    
201        /**
202         * creates model with WMS request from the RPCStruct request parameter.
203         *
204         * @param struc
205         * @return
206         */
207        private HashMap[] createWMSRequestModel( RPCStruct struc ) {
208    
209            RPCMember[] member = struc.getMembers();
210            HashMap<String,String>[] getMR = new HashMap[member.length];
211    
212            String request = "";
213            //for ( int i = 0; i < member.length; i++ ) {
214            for ( int i = member.length - 1; i >= 0; i-- ) {
215                request = (String) member[i].getValue();
216                getMR[i] = toMap( request );
217                StringTokenizer st = new StringTokenizer( request, "?" );
218                getMR[i].put( "URL", st.nextToken() );
219            }
220            return getMR;
221        }
222    
223        /**
224         * calculates images size in dependency on chosen paperFormat, resolution
225         * and orientation.
226         *
227         * @param struct
228         * @param model
229         * @return
230         */
231        private int[] calcImageSize( RPCStruct struct, HashMap model ) {
232            double width = 0;
233            double height = 0;
234            double mapSize = 0;
235    
236            double mapWI = Double.parseDouble( (String) model.get( "WIDTH" ) );
237            double mapHE = Double.parseDouble( (String) model.get( "HEIGHT" ) );
238    
239            String paperFormat = (String) struct.getMember( "paperFormat" ).getValue();
240            String resolution = (String) struct.getMember( "resolution" ).getValue();
241            String orientation = (String) struct.getMember( "orientation" ).getValue();
242    
243            if ( paperFormat.equals( "A4" ) ) {
244                if ( orientation.equals( "hoch" ) ) {
245                    width = 8.2;
246                    height = 11.6;
247                    mapSize = 6.5; //legend beside
248                } else {
249                    width = 11.6;
250                    height = 8.2;
251                    mapSize = 9.5;
252                }
253            } else if ( paperFormat.equals( "A3" ) ) {
254                if ( orientation.equals( "hoch" ) ) {
255                    width = 11.6;
256                    height = 16.5;
257                    mapSize = 9.8; //legend beside
258                } else {
259                    width = 16.5;
260                    height = 11.6;
261                    mapSize = 14;
262                }
263            } else if ( paperFormat.equals( "A5" ) ) {
264                if ( orientation.equals( "hoch" ) ) {
265                    width = 5.8;
266                    height = 8.2;
267                    mapSize = 4.1; //legend beside
268                } else {
269                    width = 8.2;
270                    height = 5.8;
271                    mapSize = 6.5;
272                }
273            }
274    
275            width = width * Double.parseDouble( resolution );
276            height = height * Double.parseDouble( resolution );
277            mapSize = mapSize * Double.parseDouble( resolution );
278    
279            int xmap = (int) Math.round( mapSize );
280            double fac = mapWI / mapHE;
281            int ymap = (int) Math.round( mapSize / fac );
282            int mapStart = 45;
283            int[] imagesize = new int[] { (int) Math.round( width ), (int) Math.round( height ), xmap,
284                                          ymap, mapStart };
285    
286            return imagesize;
287        }
288    
289        /**
290         * calculates size (width and height) of legend depending on
291         * chosen paperFormat and resolution.
292         *
293         * @param struct
294         * @param map
295         * @return
296         */
297        private Rectangle calcLegendSize( RPCStruct struct, HashMap map ) {
298    
299            String paperFormat = (String) struct.getMember( "paperFormat" ).getValue();
300            String resolution = (String) struct.getMember( "resolution" ).getValue();
301    
302            String[] layers = (String[]) map.get( "NAMES" );
303            BufferedImage[] legs = (BufferedImage[]) map.get( "IMAGES" );
304    
305            int w = 0;
306            int h = 0;
307            int size = 12;
308            double tmph1 = 0;
309            double tmph2 = 0;
310    
311            if ( paperFormat.equals( "A4" ) ) {
312                tmph1 = size / 3d;
313            } else if ( paperFormat.equals( "A3" ) ) {
314                tmph1 += 2 * size / 3;
315            }
316    
317            double res = Double.parseDouble( resolution );
318            tmph2 = ( ( res - 150 ) / 150d ) * size;
319            size += (int) Math.round( tmph2 + tmph1 );
320            for ( int i = 0; i < layers.length; i++ ) {
321                h += ( legs[i].getHeight() + 6 );
322    
323                Graphics g = legs[i].getGraphics();
324                Font f = new Font( g.getFont().getFontName(), g.getFont().getStyle(), size );
325                g.setFont( f );
326                Rectangle2D rect = g.getFontMetrics().getStringBounds( layers[i], g );
327                g.dispose();
328    
329                if ( rect.getWidth() > w ) {
330                    w = (int) rect.getWidth();
331                }
332            }
333            w += 150;
334    
335            return new Rectangle( w, h );
336        }
337    
338        /**
339         * calculates map size in dependency of the chosen paperFormat and resolution.
340         *
341         * @param model
342         * @param rectLegend
343         * @param width
344         * @return
345         */
346        private Rectangle calcMapSize( HashMap[] model, Rectangle rectLegend, int width ) {
347            int w = width - rectLegend.width - 20;
348            double wi = Double.parseDouble( (String) model[0].get( "WIDTH" ) );
349            double he = Double.parseDouble( (String) model[0].get( "HEIGHT" ) );
350            double fac = he / wi;
351            int h = (int) Math.round( fac * w );
352    
353            return new Rectangle( w, h );
354        }
355    
356        /**
357         * draws legend with symbols and name of the layers to the background BufferedImage.
358         *
359         * @param map
360         * @param bi
361         * @param start
362         * @return
363         */
364        private BufferedImage drawLegendToBI( HashMap map, BufferedImage bi, int start ) {
365    
366            int h = 5;
367            Graphics g = bi.getGraphics();
368            g.setColor( Color.WHITE );
369            String[] layers = (String[]) map.get( "NAMES" );
370            BufferedImage[] legs = (BufferedImage[]) map.get( "IMAGES" );
371    
372            for ( int i = layers.length - 1; i >= 0; i-- ) {
373                g.drawImage( legs[i], start + 10, h, null );
374                g.setColor( Color.BLACK );
375    
376                if ( legs[i].getHeight() < 50 ) {
377                    g.drawString( layers[i], start + 25 + legs[i].getWidth(),
378                                  h + (int) ( legs[i].getHeight() / 1.2 ) );
379                }
380    
381                h += ( legs[i].getHeight() + 5 );
382            }
383    
384            g.dispose();
385            return bi;
386        }
387    
388        /**
389         * modifies width and height in the WMSGetMapRequest
390         * in dependency of the chosen paperFormat and resolution.
391         * New width and height are calculated in the method "calcMapSize".
392         *
393         * @param rectMap
394         * @param model
395         * @param width
396         * @param height
397         * @return
398         */
399        private HashMap<String,Object>[] modifyModelSize( Rectangle rectMap, HashMap<String,Object>[] model, int width, int height ) {
400            int w = rectMap.width;
401            double fac = (double) height / (double) width;
402            double h = fac * w;
403    
404            for ( int i = 0; i < model.length; i++ ) {
405                model[i].put( "HEIGHT", "" + (int) Math.round( h ) );
406                model[i].put( "WIDTH", "" + w );
407            }
408    
409            return model;
410        }
411    
412        /**
413         * gets the map with corresponding mapsizes built-in the urls.
414         * @throws UnknownCRSException
415         *
416         * @param model
417         * @return
418         * @throws MalformedURLException
419         * @throws IOException
420         * @throws XMLParsingException
421         * @throws InconsistentRequestException
422         * @throws OGCWebServiceException
423         * @throws UnknownCRSException
424         */
425        private BufferedImage getMap( HashMap<String,String>[] model )
426                                throws MalformedURLException, IOException, XMLParsingException,
427                                InconsistentRequestException, OGCWebServiceException {
428            int w = Integer.parseInt( model[0].get( "WIDTH" ) );
429            int h = Integer.parseInt( model[0].get( "HEIGHT" ) );
430            BufferedImage bJ = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB );
431            Graphics g = bJ.getGraphics();
432            g.setColor( Color.WHITE );
433            g.fillRect( 1, 1, bJ.getWidth() - 2, bJ.getHeight() - 2 );
434            g.dispose();
435            GetMap gmr = null;
436    
437            for ( int i = model.length - 1; i >= 0; i-- ) {
438                String urls = OWSUtils.validateHTTPGetBaseURL( model[i].remove( "URL" ) );
439                String s = URLDecoder.decode( model[i].get( "FORMAT" ),
440                                              CharsetUtils.getSystemCharset() );
441                model[i].put( "FORMAT", s );
442                model[i].put( "ID", "1.1.1" );
443                gmr = GetMap.create( model[i] );
444                /*
445                 if ( sessionid != null ) {
446                    urls = StringTools.concat( 1000, urls, "&sessionID=", sessionid.getValue(), '&' );
447                 }
448                 */
449                URL url = new URL( urls + gmr.getRequestParameter() );
450                InputStream is = url.openStream();
451                BufferedImage tmp = ImageIO.read( is );
452                is.close();
453                g = bJ.getGraphics();
454                g.drawImage( tmp, 0, 0, null );
455                g.dispose();
456            }
457    
458            return bJ;
459        }
460    
461        /**
462         * draws the map to the background BufferedImage
463         *
464         * @param reqIm
465         * @param bi
466         * @param mapStart
467         * @return
468         */
469        private BufferedImage drawMapToBI( BufferedImage reqIm, BufferedImage bi, int mapStart ) {
470            Graphics g = bi.getGraphics();
471            g.drawImage( reqIm, mapStart, mapStart, null );
472            g.dispose();
473    
474            return bi;
475        }
476    
477        /**
478         * saves image with BufferedImage including map, legend and scalebar in
479         * chosen image format and directory set in mapcontext.xml file.
480         * Via the attribute "ImageSource" the image can be called for.
481         *
482         * @param vc
483         * @param struct
484         * @param bg
485         */
486        private void saveImage( ViewContext vc, RPCStruct struct, BufferedImage bg ) {
487            String format = (String) struct.getMember( "format" ).getValue();
488            format = format.substring( format.indexOf( '/' ) + 1, format.length() );
489            GeneralExtension ge = vc.getGeneral().getExtension();
490            IOSettings ios = ge.getIOSettings();
491            String dir = ios.getPrintDirectory().getDirectoryName();
492    
493            long l = IDGenerator.getInstance().generateUniqueID() % 100;
494            String file = "Map" + l + '.' + format;
495    
496            try {
497                String outPut = new URL( dir ).getFile() + '/' + file;
498                File f = new File( outPut );
499                f.deleteOnExit();
500                FileOutputStream fos = new FileOutputStream( f );
501                ImageUtils.saveImage( bg, fos, format, 1 );
502            } catch ( Exception e ) {
503                LOG.logError( "Error occurred in saving image_: ", e );
504            }
505    
506            String access = OWSUtils.validateHTTPGetBaseURL( ios.getPrintDirectory().getOnlineResource().toExternalForm() )
507                            + "request=download&filename=" + file;
508    
509            this.getRequest().setAttribute( "ImageSource", access );
510            this.getRequest().setAttribute( "ImageWidth", new Integer( bg.getWidth() ) );
511            this.getRequest().setAttribute( "ImageHeight", new Integer( bg.getHeight() ) );
512    
513        }
514    
515        /**
516         * gets parameters of the LegendRequest
517         *
518         * @return
519         * @throws InconsistentRequestException
520         */
521        private GetLegendGraphic getLegendRequestParameter()
522                                throws InconsistentRequestException {
523            HashMap<String,String> legend = toMap( "VERSION=1.1.1&REQUEST=GetLegendGraphic&FORMAT=image/png&WIDTH=50&HEIGHT=50&"
524                                    + "EXCEPTIONS=application/vnd.ogc.se_inimage&LAYER=europe:major_rivers&STYLE=default&"
525                                    + "SLD=file:///C:/Projekte/UmweltInfo/deegreewms/WEB-INF/xml/styles.xml" );
526            return GetLegendGraphic.create( legend );
527    
528        }
529    
530        /**
531         * gets legend with layers and styles. The size of the symbols is adjusted to the
532         * chosen paperFomrat and resolution.
533         *
534         * @param struct
535         * @param glr
536         * @param model
537         * @return
538         */
539        private HashMap<String,Object> getLegend( RPCStruct struct, GetLegendGraphic glr, HashMap[] model ) {
540    
541            ArrayList<String> list1 = new ArrayList<String>();
542            ArrayList<BufferedImage> list2 = new ArrayList<BufferedImage>();
543    
544            String format = glr.getFormat();
545            if ( format.equals( "image/jpg" ) )
546                format = "image/jpeg";
547    
548            String legendURL = "";
549    
550            String paperFormat = (String) struct.getMember( "paperFormat" ).getValue();
551            String resolution = (String) struct.getMember( "resolution" ).getValue();
552            int h = 15;
553            int w = 15;
554            double tmph1 = 0;
555            double tmpw1 = 0;
556            double tmph2 = 0;
557            double tmpw2 = 0;
558    
559            if ( paperFormat.equals( "A4" ) ) {
560                tmph1 = h / 3d;
561                tmpw1 = w / 3d;
562            } else if ( paperFormat.equals( "A3" ) ) {
563                tmph1 = 2 * h / 3d;
564                tmpw1 = 2 * w / 3d;
565            }
566    
567            double res = Double.parseDouble( resolution );
568            tmph2 = ( ( res - 150 ) / 150d ) * h;
569            tmpw2 = ( ( res - 150 ) / 150d ) * w;
570    
571            w += (int) Math.round( tmpw1 + tmpw2 );
572            h += (int) Math.round( tmph1 + tmph2 );
573    
574            for ( int i = 0; i < model.length; i++ ) {
575                if ( model[i].get( "SLD" ) != null ) {
576                    continue;
577                }
578                String[] lays = StringTools.toArray( (String) model[i].get( "LAYERS" ), ",", false );
579    
580                String style = (String) model[i].get( "STYLES" );
581                String[] styles = new String[lays.length];
582                for ( int j = 0; j < styles.length; j++ ) {
583                    styles[j] = "default";
584                }
585    
586                if ( style != null && !style.trim().equals( "" ) ) {
587                    //styles = StringTools.toArray(style,",",false);
588                    if ( ( StringTools.toArray( style, ",", false ) ).length != 0 ) {
589                        styles = StringTools.toArray( style, ",", false );
590                    }
591                } else {
592                    styles = new String[lays.length];
593                    for ( int j = 0; j < styles.length; j++ ) {
594                        styles[j] = "default";
595                    }
596                }
597    
598                if ( styles == null ) {
599                    styles = new String[lays.length];
600                    for ( int j = 0; j < styles.length; j++ ) {
601                        styles[j] = "default";
602                    }
603                }
604    
605                for ( int j = 0; j < lays.length; j++ ) {
606                    String layer = lays[j];
607    
608                    //added to prevent ArrayOutOfBoundsException
609                    String stl = "default";
610                    if ( j < styles.length ) {
611                        stl = styles[j];
612                    }
613    
614                    legendURL = createLegendURL( w, h, layer, stl, format, glr, model[i] );
615                    BufferedImage legendGraphic = null;
616                    try {
617                        InputStream is = new URL( legendURL ).openStream();
618                        legendGraphic = ImageIO.read( is );
619                        is.close();
620                    } catch ( Exception e ) {
621                        System.out.println( "\n\nLegend graphic for layer '" + layer
622                                            + "' is not available. Skipping.\n\n" );
623                        legendGraphic = null;
624                        e.printStackTrace();
625                    }
626                    if ( legendGraphic != null ) {
627                        list1.add( layer );
628                        list2.add( legendGraphic );
629                    }
630                }
631            }
632    
633            String[] layers = list1.toArray( new String[list1.size()] );
634            BufferedImage[] legs = list2.toArray( new BufferedImage[list2.size()] );
635            HashMap<String,Object> map = new HashMap<String,Object>();
636            map.put( "NAMES", layers );
637            map.put( "IMAGES", legs );
638    
639            return map;
640        }
641    
642        /**
643         * creates legend URL with corresponding key values.
644         *
645         * @param w
646         * @param h
647         * @param layer
648         * @param style
649         * @param format
650         * @param glr
651         * @param model
652         * @return
653         */
654        private String createLegendURL( int w, int h, String layer, String style, String format,
655                                       GetLegendGraphic glr, HashMap model ) {
656    
657            String s = null;
658            try {
659                if ( "default".equals( style ) ) {
660                    style = "";
661                }
662                String url = OWSUtils.validateHTTPGetBaseURL( (String) model.get( "URL" ) );
663                s = StringTools.concat( 500, url, "service=WMS", "&VERSION=", glr.getVersion(),
664                                        "&REQUEST=GetLegendGraphic", "&FORMAT=", format, "&WIDTH=", w,
665                                        "&HEIGHT=", h,
666                                        "&EXCEPTIONS=application/vnd.ogc.se_inimage&LAYER=",
667                                        URLDecoder.decode( layer, CharsetUtils.getSystemCharset() ),
668                                        "&STYLE=", style );
669                // insufficient information available for user restrictions
670                // TODO
671                //HttpServletRequest req = (HttpServletRequest) getRequest();
672                //if ( req.getUserPrincipal() != null ) {
673                //    String user = req.getUserPrincipal().getName();
674                //    if ( user.indexOf( "\\" ) > 1 ) {
675                //        String[] us = StringTools.toArray( user, "\\", false );
676                //        user = us[us.length - 1];
677                //    }
678                //    s = StringTools.concat( 500, s, "&user=", user );
679                //}
680    
681            } catch ( UnsupportedEncodingException e ) {
682                // should never happen
683                e.printStackTrace();
684            }
685            return s;
686        }
687    }