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