    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    }