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 }