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 }