001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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    }