    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/portal/portlet/enterprise/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.portlet.enterprise;
    037
    038    import java.io.File;
    039    import java.io.IOException;
    040    import java.io.RandomAccessFile;
    041    import java.io.StringReader;
    042    import java.util.UUID;
    043
    044    import javax.servlet.ServletContext;
    045    import javax.servlet.http.HttpServletRequest;
    046    import javax.servlet.http.HttpSession;
    047
    048    import org.deegree.enterprise.control.AbstractListener;
    049    import org.deegree.enterprise.control.FormEvent;
    050    import org.deegree.enterprise.control.RPCMember;
    051    import org.deegree.enterprise.control.RPCStruct;
    052    import org.deegree.enterprise.control.RPCWebEvent;
    053    import org.deegree.framework.log.ILogger;
    054    import org.deegree.framework.log.LoggerFactory;
    055    import org.deegree.framework.util.StringTools;
    056    import org.deegree.framework.xml.XMLFragment;
    057    import org.deegree.model.spatialschema.Envelope;
    058    import org.deegree.model.spatialschema.GMLGeometryAdapter;
    059    import org.deegree.model.spatialschema.GeometryFactory;
    060    import org.deegree.model.spatialschema.Point;
    061    import org.deegree.ogcwebservices.OGCWebServiceException;
    062    import org.deegree.ogcwebservices.wmps.WMPService;
    063    import org.deegree.ogcwebservices.wmps.WMPServiceFactory;
    064    import org.deegree.ogcwebservices.wmps.configuration.WMPSConfiguration;
    065    import org.deegree.ogcwebservices.wmps.configuration.WMPSConfigurationDocument;
    066    import org.deegree.ogcwebservices.wmps.operation.PrintMap;
    067    import org.deegree.ogcwebservices.wmps.operation.PrintMapResponse;
    068    import org.deegree.portal.PortalException;
    069    import org.deegree.portal.context.Layer;
    070    import org.deegree.portal.context.ViewContext;
    071    import org.deegree.portal.portlet.modules.actions.IGeoPortalPortletPerform;
    072
    073    /**
    074     * performs a print request/event by creating a PDF document from the current map
    075     *
    076     *
    077     * @version $Revision: 18195 $
    078     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    079     * @author last edited by: $Author: mschneider $
    080     *
    081     * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    082     *
    083     * @since 2.0
    084     */
    085    public class PrintListener extends AbstractListener {
    086
    087        private static ILogger LOG = LoggerFactory.getLogger( PrintListener.class );
    088
    089        /**
    090         * @param e
    091         */
    092        @Override
    093        public void actionPerformed( FormEvent e ) {
    094            RPCWebEvent rpc = (RPCWebEvent) e;
    095            try {
    096                validate( rpc );
    097            } catch ( Exception ex ) {
    098                LOG.logError( ex.getMessage(), ex );
    099                gotoErrorPage( ex.getMessage() );
    100            }
    101
    102            ViewContext vc = getViewContext( rpc );
    103            if ( vc == null ) {
    104                LOG.logError( "no valid ViewContext available; maybe your session has reached tieout limit" );
    105                gotoErrorPage( "no valid ViewContext available; maybe your session has reached tieout limit" );
    106                setNextPage( "igeoportal/error.jsp" );
    107                return;
    108            }
    109            try {
    110                printMap( vc, rpc );
    111            } catch ( Exception ex ) {
    112                ex.printStackTrace();
    113                LOG.logError( ex.getMessage(), ex );
    114                gotoErrorPage( ex.getMessage() );
    115                setNextPage( "igeoportal/error.jsp" );
    116            }
    117        }
    118
    119        /**
    120         *
    121         * @param vc
    122         * @param rpc
    123         * @throws PortalException
    124         */
    125        private void printMap( ViewContext vc, RPCWebEvent rpc )
    126                                throws PortalException {
    127
    128            String template = readRequestTemplate();
    129
    130            template = fillTemplate( vc, rpc, template );
    131
    132            StringReader sr = new StringReader( template );
    133            XMLFragment xml = new XMLFragment();
    134            try {
    135                xml.load( sr, XMLFragment.DEFAULT_URL );
    136            } catch ( Exception e ) {
    137                LOG.logError( e.getMessage(), e );
    138                throw new PortalException( "could not create a DOM object from PrintMap request Template", e );
    139            }
    140
    141            PrintMap printMap = null;
    142            try {
    143                printMap = PrintMap.create( xml.getRootElement() );
    144            } catch ( Exception e ) {
    145                LOG.logError( e.getMessage(), e );
    146                throw new PortalException( "could not parse PrintMap request.", e );
    147            }
    148
    149            if ( !WMPServiceFactory.isInitialized() ) {
    150                WMPSConfiguration wmpsConf = readWMPSConfiguration();
    151                WMPServiceFactory.setConfiguration( wmpsConf );
    152            }
    153            WMPService wmps = WMPServiceFactory.getService();
    154            Object result = null;
    155            try {
    156                result = wmps.doService( printMap );
    157            } catch ( OGCWebServiceException e ) {
    158                e.printStackTrace();
    159                LOG.logError( "could not perform PrintMap request ", e );
    160                throw new PortalException( "could not perform PrintMap request ", e );
    161            }
    162            if ( result instanceof PrintMapResponse ) {
    163                // TODO
    164                // handle result from asynchronous request processing
    165            } else {
    166                forwardPDF( result );
    167            }
    168
    169        }
    170
    171        private void forwardPDF( Object result )
    172                                throws PortalException {
    173            // must be a byte array
    174            String tempDir = getInitParameter( "TEMPDIR" );
    175            if ( !tempDir.endsWith( "/" ) ) {
    176                tempDir = tempDir + '/';
    177            }
    178            if ( tempDir.startsWith( "/" ) ) {
    179                tempDir = tempDir.substring( 1, tempDir.length() );
    180            }
    181
    182            ServletContext sc = ( (HttpServletRequest) this.getRequest() ).getSession( true ).getServletContext();
    183
    184            String s = StringTools.concat( 200, sc.getRealPath( tempDir ), '/', UUID.randomUUID().toString(), ".pdf" );
    185            try {
    186                RandomAccessFile raf = new RandomAccessFile( s, "rw" );
    187                raf.write( (byte[]) result );
    188                raf.close();
    189            } catch ( Exception e ) {
    190                e.printStackTrace();
    191                LOG.logError( "could not write temporary pdf file: " + s, e );
    192                throw new PortalException( "could not write temporary pdf file: " + s, e );
    193            }
    194
    195            getRequest().setAttribute( "PDF", StringTools.concat( 200, tempDir, UUID.randomUUID().toString(), ".pdf" ) );
    196        }
    197
    198        /**
    199         * reads WMPS configuration from the source defined in the listeners init parameters (
    200         * 'WMPSCONFIG' )
    201         *
    202         * @return the configuration
    203         * @throws PortalException
    204         */
    205        private WMPSConfiguration readWMPSConfiguration()
    206                                throws PortalException {
    207            String config = getInitParameter( "WMPSCONFIG" );
    208            if ( config == null ) {
    209                throw new PortalException( "no WMPS configuration defined for PrintListener" );
    210            }
    211            File file = new File( config );
    212            if ( !file.isAbsolute() ) {
    213                ServletContext sc = ( (HttpServletRequest) this.getRequest() ).getSession( true ).getServletContext();
    214                file = new File( sc.getRealPath( config ) );
    215            }
    216            WMPSConfiguration wmpsConf = null;
    217            try {
    218                WMPSConfigurationDocument wmpsConfDoc = new WMPSConfigurationDocument();
    219                wmpsConfDoc.load( file.toURL() );
    220                wmpsConf = wmpsConfDoc.parseConfiguration();
    221            } catch ( Exception e ) {
    222                LOG.logError( "could not read/create WMPSConfiguration: " + file, e );
    223                throw new PortalException( "could not read/create WMPSConfiguration: " + file, e );
    224            }
    225            return wmpsConf;
    226        }
    227
    228        /**
    229         * fills the passed PrintMap request template with required values
    230         *
    231         * @param vc
    232         * @param rpc
    233         * @param template
    234         * @return the html with the filled in template.
    235         */
    236        private String fillTemplate( ViewContext vc, RPCWebEvent rpc, String template ) {
    237            // set boundingbox/envelope
    238            Point[] points = vc.getGeneral().getBoundingBox();
    239            Envelope env = GeometryFactory.createEnvelope( points[0].getX(), points[0].getY(), points[1].getX(),
    240                                                           points[1].getY(), points[0].getCoordinateSystem() );
    241            String envS = GMLGeometryAdapter.exportAsEnvelope( env ).toString();
    242            template = StringTools.replace( template, "$ENV$", envS, false );
    243
    244            // set layers
    245            StringBuffer lys = new StringBuffer( 1000 );
    246            Layer[] layers = vc.getLayerList().getLayers();
    247            for ( int i = 0; i < layers.length; i++ ) {
    248                if ( !layers[i].isHidden() ) {
    249                    lys.append( "<sld:NamedLayer>" );
    250                    lys.append( "<sld:Named>" );
    251                    lys.append( layers[i] );
    252                    lys.append( "</sld:Named>" );
    253                    lys.append( "<sld:NamedStyle>" );
    254                    lys.append( "<sld:Named>" );
    255                    lys.append( layers[i].getStyleList().getCurrentStyle().getName() );
    256                    lys.append( "</sld:Named>" );
    257                    lys.append( "</sld:NamedStyle>" );
    258                    lys.append( "</sld:NamedLayer>" );
    259                }
    260            }
    261            template = StringTools.replace( template, "$LAYERS$", lys.toString(), false );
    262
    263            // set print template
    264            RPCStruct struct = (RPCStruct) rpc.getRPCMethodCall().getParameters()[0].getValue();
    265            String printTemplate = (String) struct.getMember( "TEMPLATE" ).getValue();
    266            template = StringTools.replace( template, "$TEMPLATE$", printTemplate, false );
    267
    268            // set text area values
    269            StringBuffer ta = new StringBuffer( 1000 );
    270            RPCMember[] members = struct.getMembers();
    271            for ( int i = 0; i < members.length; i++ ) {
    272                if ( members[i].getName().startsWith( "TA:" ) ) {
    273                    ta.append( "<TextArea>" );
    274                    ta.append( "<Name>" );
    275                    ta.append( members[i].getName().substring( 3, members[i].getName().length() ) );
    276                    ta.append( "</Name>" );
    277                    ta.append( "<Text>" );
    278                    ta.append( members[i].getValue() );
    279                    ta.append( "</Text>" );
    280                    ta.append( "</TextArea>" );
    281                }
    282            }
    283            template = StringTools.replace( template, "$TEXTAREAS$", ta.toString(), false );
    284            return template;
    285        }
    286
    287        /**
    288         * read PrintMap request template from the source defined in the listeners init parameters (
    289         * 'PRINTMAPTEMPLATE' )
    290         *
    291         * @return the template as a String.
    292         * @throws PortalException
    293         */
    294        private String readRequestTemplate()
    295                                throws PortalException {
    296            String reqTemplate = getInitParameter( "PRINTMAPTEMPLATE" );
    297            if ( reqTemplate == null ) {
    298                throw new PortalException( "not PrintMap request template defined for PrintListener" );
    299            }
    300            File file = new File( reqTemplate );
    301            if ( !file.isAbsolute() ) {
    302                ServletContext sc = ( (HttpServletRequest) this.getRequest() ).getSession( true ).getServletContext();
    303                file = new File( sc.getRealPath( reqTemplate ) );
    304            }
    305            byte[] b;
    306            try {
    307                RandomAccessFile raf = new RandomAccessFile( file, "r" );
    308                b = new byte[(int) raf.length()];
    309                raf.read( b );
    310                raf.close();
    311            } catch ( IOException e ) {
    312                String s = "Could not read PrintMap request template: " + file;
    313                LOG.logError( s, e );
    314                throw new PortalException( s );
    315            }
    316            return new String( b );
    317        }
    318
    319        /**
    320         * reads the view context to print from the users session
    321         *
    322         * @param rpc
    323         * @return the context
    324         */
    325        private ViewContext getViewContext( RPCWebEvent rpc ) {
    326            RPCStruct struct = (RPCStruct) rpc.getRPCMethodCall().getParameters()[0].getValue();
    327            String mmid = (String) struct.getMember( "MAPMODELID" ).getValue();
    328            HttpSession session = ( (HttpServletRequest) getRequest() ).getSession();
    329            return IGeoPortalPortletPerform.getCurrentViewContext( session, mmid );
    330        }
    331
    332        /**
    333         * validates the incoming request/RPC if conatins all required elements
    334         *
    335         * @param rpc
    336         * @throws PortalException
    337         */
    338        private void validate( RPCWebEvent rpc )
    339                                throws PortalException {
    340            RPCStruct struct = (RPCStruct) rpc.getRPCMethodCall().getParameters()[0].getValue();
    341            if ( struct.getMember( "TEMPLATE" ) == null ) {
    342                throw new PortalException( "struct member: 'TEMPLATE' must be set" );
    343            }
    344            if ( struct.getMember( "MAPMODELID" ) == null ) {
    345                throw new PortalException( "struct member: 'MAPMODELID' must be set" );
    346            }
    347        }
    348
    349    }