001    /*----------------------------------------------------------------------------
002     This file is part of BfS WPS WebApplication project
003     
004     Contact information:
005    
006     lat/lon GmbH
007     Aennchenstr. 19, 53177 Bonn
008     Germany
009     http://lat-lon.de/
010    
011     ----------------------------------------------------------------------------*/
012    package org.deegree.enterprise.servlet;
013    
014    import java.awt.BasicStroke;
015    import java.awt.Color;
016    import java.awt.Graphics;
017    import java.awt.Graphics2D;
018    import java.awt.Rectangle;
019    import java.awt.TexturePaint;
020    import java.awt.geom.GeneralPath;
021    import java.awt.image.BufferedImage;
022    import java.io.File;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.io.OutputStream;
026    import java.io.PrintWriter;
027    import java.net.URL;
028    import java.util.Map;
029    import java.util.Properties;
030    
031    import javax.servlet.ServletException;
032    import javax.servlet.http.HttpServlet;
033    import javax.servlet.http.HttpServletRequest;
034    import javax.servlet.http.HttpServletResponse;
035    import javax.servlet.http.HttpSession;
036    
037    import org.deegree.framework.log.ILogger;
038    import org.deegree.framework.log.LoggerFactory;
039    import org.deegree.framework.util.GeometryUtils;
040    import org.deegree.framework.util.ImageUtils;
041    import org.deegree.framework.util.KVP2Map;
042    import org.deegree.framework.util.StringTools;
043    import org.deegree.graphics.transformation.GeoTransform;
044    import org.deegree.graphics.transformation.WorldToScreenTransform;
045    import org.deegree.model.spatialschema.Curve;
046    import org.deegree.model.spatialschema.Envelope;
047    import org.deegree.model.spatialschema.Geometry;
048    import org.deegree.model.spatialschema.GeometryException;
049    import org.deegree.model.spatialschema.MultiPrimitive;
050    import org.deegree.model.spatialschema.Point;
051    import org.deegree.model.spatialschema.Position;
052    import org.deegree.model.spatialschema.Surface;
053    import org.deegree.model.spatialschema.SurfacePatch;
054    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
055    import org.deegree.ogcwebservices.wms.operation.GetMap;
056    
057    /**
058     * This servlet realizes a OGC:WMS that just offers one layer ('highlight') reading a geometry form session of
059     * requesting user. The geometry to be painted must be stored in a session attribute named 'TEMP_WMS_GEOMETRY'.
060     * Following init parameters ars upported:
061     * <ul>
062     * <li>FILL: fill color for polygons (optional)
063     * <li>STROKE: stroke color for lines (optional)
064     * <li>PATTERN: fill pattern/image for polygon (if available FILL will be ignored) (optional)
065     * <li>SYMBOL: symbol image for points (optional)
066     * </ul>
067     * 
068     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
069     * 
070     * @author last edited by: $Author: apoth $
071     * 
072     * @version $Revision: 30359 $, $Date: 2011-04-04 21:23:10 +0200 (Mon, 04 Apr 2011) $
073     * 
074     */
075    public class SessionWMS extends HttpServlet {
076    
077        private static final long serialVersionUID = 7263960291096038482L;
078    
079        private static final ILogger LOG = LoggerFactory.getLogger( SessionWMS.class );
080    
081        private static Color fillColor = new Color( 1f, 1f, 1f, 0.5f );
082    
083        private static Color lineColor = Color.BLACK;
084        
085        private static float polyStrokeWidth = 1;
086        
087        private static float strokeStrokeWidth = 1;
088    
089        private static BufferedImage fillPattern;
090    
091        private static BufferedImage symbol;
092    
093        private static String capa;
094    
095        @Override
096        public void init()
097                                throws ServletException {
098            // TODO Auto-generated method stub
099            super.init();
100            if ( getInitParameter( "FILL" ) != null ) {
101                fillColor = Color.decode( getInitParameter( "FILL" ) );
102            }
103            if ( getInitParameter( "STROKE" ) != null ) {
104                lineColor = Color.decode( getInitParameter( "STROKE" ) );
105            }
106            if ( getInitParameter( "STROKEWIDTH" ) != null ) {
107                strokeStrokeWidth = Float.parseFloat(  getInitParameter( "STROKEWIDTH" ) );
108            }
109            if ( getInitParameter( "FILLSTROKEWIDTH" ) != null ) {
110                polyStrokeWidth = Float.parseFloat(  getInitParameter( "FILLSTROKEWIDTH" ) );
111            }
112            if ( getInitParameter( "PATTERN" ) != null ) {
113                File pattern = new File( getInitParameter( "PATTERN" ) );
114                if ( !pattern.isAbsolute() ) {
115                    String s = getServletContext().getRealPath( getInitParameter( "PATTERN" ) );
116                    pattern = new File( s );
117                }
118                try {
119                    fillPattern = ImageUtils.loadImage( pattern );
120                } catch ( IOException e ) {
121                    LOG.logError( e );
122                    throw new ServletException( e );
123                }
124            }
125            if ( getInitParameter( "SYMBOL" ) != null ) {
126                File pattern = new File( getInitParameter( "SYMBOL" ) );
127                if ( !pattern.isAbsolute() ) {
128                    String s = getServletContext().getRealPath( getInitParameter( "SYMBOL" ) );
129                    pattern = new File( s );
130                }
131                try {
132                    symbol = ImageUtils.loadImage( pattern );
133                } catch ( IOException e ) {
134                    LOG.logError( e );
135                    throw new ServletException( e );
136                }
137            } else {
138                symbol = new BufferedImage( 9, 9, BufferedImage.TYPE_INT_ARGB );
139                Graphics g = symbol.getGraphics();
140                g.setColor( Color.RED );
141                g.fillOval( 0, 0, 9, 9 );
142                g.dispose();
143            }
144            Properties prop = new Properties();
145            InputStream is = SessionWMS.class.getResourceAsStream( "session-wms.properties" );
146            try {
147                prop.load( is );
148                is.close();
149            } catch ( IOException e ) {
150                LOG.logError( e );
151                throw new ServletException( e );
152            }
153            capa = prop.getProperty( "capabilities" );
154    
155        }
156    
157        @Override
158        protected void doGet( HttpServletRequest req, HttpServletResponse resp )
159                                throws ServletException, IOException {
160            Map<String, String> param = KVP2Map.toMap( req );
161            param.put( "ID", "1" );
162            resp.setHeader( "Cache-Control", "no-cache, no-store" );
163            resp.setHeader( "Pragma", "no-cache" );
164    
165            if ( "GetCapabilities".equals( param.get( "REQUEST" ) ) ) {
166                PrintWriter pw = resp.getWriter();
167                String s = StringTools.replace( capa, "§URL§", req.getRequestURL().toString(), true );
168                pw.write( s );
169                pw.close();
170            } else if ( "GetMap".equals( param.get( "REQUEST" ) ) ) {
171                getMap( req, resp, param );
172            } else if ( "GetLegendGraphic".equals( param.get( "REQUEST" ) ) ) {
173                getLegendGraphic( req, resp, param );
174            }
175    
176        }
177    
178        private void getMap( HttpServletRequest req, HttpServletResponse resp, Map<String, String> param ) {
179            try {
180                GetMap getMap = GetMap.create( param );
181                HttpSession session = req.getSession();
182                Geometry geometry = (Geometry) session.getAttribute( "TEMP_WMS_GEOMETRY" );
183                if ( geometry != null ) {
184                    BufferedImage bi = new BufferedImage( getMap.getWidth(), getMap.getHeight(),
185                                                          BufferedImage.TYPE_INT_ARGB );
186                    // set background to white
187                    Graphics g = bi.getGraphics();
188                    g.setColor( new Color( 0, 0, 0, 0f ) );
189                    g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() );
190    
191                    Envelope bbox = getMap.getBoundingBox();
192                    GeoTransform gt = new WorldToScreenTransform( bbox.getMin().getX(), bbox.getMin().getY(),
193                                                                  bbox.getMax().getX(), bbox.getMax().getY(), 0, 0,
194                                                                  getMap.getWidth() - 1, getMap.getHeight() - 1 );
195                    if ( geometry instanceof MultiPrimitive ) {
196                        Geometry[] geometries = ( (MultiPrimitive) geometry ).getAll();
197                        for ( Geometry geom : geometries ) {
198                            drawGeometry( geom, (Graphics2D) g, gt );
199                        }
200                    } else {
201                        drawGeometry( geometry, (Graphics2D) g, gt );
202                    }
203    
204                    g.dispose();
205                    resp.setContentType( getMap.getFormat() );
206                    int idx = getMap.getFormat().lastIndexOf( "/" );
207                    OutputStream os = resp.getOutputStream();
208                    ImageUtils.saveImage( bi, resp.getOutputStream(), getMap.getFormat().substring( idx + 1 ), 0.99f );
209                    os.flush();
210                    os.close();
211                }
212            } catch ( Exception e ) {
213                LOG.logError( e );
214            }
215        }
216    
217        private void drawGeometry( Geometry geometry, Graphics2D g, GeoTransform gt )
218                                throws GeometryException {
219            if ( geometry instanceof Point ) {
220                int x = (int) Math.round( gt.getDestX( ( (Point) geometry ).getX() ) );
221                int y = (int) Math.round( gt.getDestY( ( (Point) geometry ).getY() ) );
222                x += symbol.getWidth() / 2 + 1;
223                y += symbol.getHeight() / 2 + 1;
224                g.drawImage( symbol, x, y, null );
225            } else if ( geometry instanceof Curve ) {
226                GeneralPath path = createPath( (Curve) geometry, gt );
227                g.setColor( lineColor );
228                g.setStroke( new BasicStroke( strokeStrokeWidth ) );
229                g.draw( path );
230            } else if ( geometry instanceof Surface ) {
231                GeneralPath path = createPath( (Surface) geometry, gt );
232                if ( fillColor != null && fillPattern == null ) {
233                    g.setColor( fillColor );                
234                } else {
235                    Rectangle anchor = new Rectangle( 0, 0, fillPattern.getWidth(), fillPattern.getHeight() );
236                    ( (Graphics2D) g ).setPaint( new TexturePaint( fillPattern, anchor ) );
237                }
238                g.fill( path );
239                if ( lineColor != null ) {
240                    g.setStroke( new BasicStroke( polyStrokeWidth ) );
241                    g.setColor( lineColor );
242                    g.draw( path );
243                }
244            }
245        }
246    
247        private GeneralPath createPath( Curve curve, GeoTransform gt )
248                                throws GeometryException {
249    
250            GeneralPath path = new GeneralPath();
251    
252            Position[] pos = curve.getAsLineString().getPositions();
253            appendPositionsToPath( path, pos, gt );
254    
255            return path;
256        }
257    
258        private GeneralPath createPath( Surface surface, GeoTransform gt ) {
259    
260            GeneralPath path = new GeneralPath();
261    
262            SurfacePatch patch = null;
263            try {
264                patch = surface.getSurfacePatchAt( 0 );
265            } catch ( GeometryException e ) {
266                LOG.logError( e.getMessage(), e );
267            }
268            appendPositionsToPath( path, patch.getExteriorRing(), gt );
269    
270            Position[][] inner = patch.getInteriorRings();
271            if ( inner != null ) {
272                for ( int i = 0; i < inner.length; i++ ) {
273                    appendPositionsToPath( path, inner[i], gt );
274                }
275            }
276    
277            return path;
278        }
279    
280        private void appendPositionsToPath( GeneralPath path, Position[] pos, GeoTransform gt ) {
281    
282            Position p = gt.getDestPoint( pos[0] );
283            float xx = (float) p.getX();
284            float yy = (float) p.getY();
285            path.moveTo( xx, yy );
286            for ( int i = 1; i < pos.length; i++ ) {
287                p = gt.getDestPoint( pos[i] );
288                float xx_ = (float) p.getX();
289                float yy_ = (float) p.getY();
290                if ( GeometryUtils.distance( xx, yy, xx_, yy_ ) > 5 || i == pos.length - 1 ) {
291                    path.lineTo( xx_, yy_ );
292                    xx = xx_;
293                    yy = yy_;
294                }
295            }
296    
297        }
298    
299        /**
300         * 
301         * @param req
302         * @param resp
303         * @param param
304         */
305        @SuppressWarnings("unchecked")
306        private void getLegendGraphic( HttpServletRequest req, HttpServletResponse resp, Map<String, String> param ) {
307            try {
308                GetLegendGraphic getLegendGraphic = GetLegendGraphic.create( param );
309                HttpSession session = req.getSession();
310                Map<String, String> imageURLs = (Map<String, String>) session.getAttribute( "legendURLs" );
311                BufferedImage bi = null;
312                String layer = getLegendGraphic.getLayer();
313                if ( imageURLs != null && imageURLs.get( layer ) != null ) {
314                    String s = imageURLs.get( layer );
315                    bi = ImageUtils.loadImage( new URL( s ) );
316                    resp.setContentType( getLegendGraphic.getFormat() );
317                    int idx = getLegendGraphic.getFormat().lastIndexOf( "/" );
318                    ImageUtils.saveImage( bi, resp.getOutputStream(), getLegendGraphic.getFormat().substring( idx + 1 ),
319                                          0.99f );
320                } else {
321                    if ( "image/png".equals( getLegendGraphic.getFormat() )
322                         || "image/gif".equals( getLegendGraphic.getFormat() ) ) {
323                        bi = new BufferedImage( 100, 100, BufferedImage.TYPE_INT_ARGB );
324                    } else {
325                        bi = new BufferedImage( 100, 100, BufferedImage.TYPE_INT_RGB );
326                    }
327                    // set background to white and draw error message
328                    Graphics g = bi.getGraphics();
329                    g.setColor( Color.WHITE );
330                    g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() );
331                    g.setColor( Color.RED );
332                    g.drawString( "no legend symbol", 10, 10 );
333                    g.drawString( "available for layer:", 10, 40 );
334                    g.drawString( layer, 10, 70 );
335                    g.dispose();
336                }
337                resp.setContentType( getLegendGraphic.getFormat() );
338                int idx = getLegendGraphic.getFormat().lastIndexOf( "/" );
339                OutputStream os = resp.getOutputStream();
340                ImageUtils.saveImage( bi, os, getLegendGraphic.getFormat().substring( idx + 1 ), 0.99f );
341                os.flush();
342                os.close();
343            } catch ( Exception e ) {
344                e.printStackTrace();
345            }
346        }
347    
348        @Override
349        protected void doPost( HttpServletRequest req, HttpServletResponse resp )
350                                throws ServletException, IOException {
351            super.doGet( req, resp );
352        }
353    
354    }