001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/enterprise/control/ApplicationHandler.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.enterprise.control; 037 038 import static org.deegree.framework.util.CharsetUtils.getSystemCharset; 039 040 import java.io.BufferedReader; 041 import java.io.File; 042 import java.io.IOException; 043 import java.io.InputStreamReader; 044 import java.io.Reader; 045 import java.io.StringReader; 046 import java.net.MalformedURLException; 047 import java.net.URL; 048 import java.net.URLDecoder; 049 import java.nio.charset.Charset; 050 import java.util.ArrayList; 051 import java.util.HashMap; 052 import java.util.List; 053 054 import javax.servlet.ServletRequest; 055 import javax.servlet.http.HttpServletRequest; 056 057 import org.deegree.datatypes.parameter.GeneralOperationParameterIm; 058 import org.deegree.datatypes.parameter.ParameterValueIm; 059 import org.deegree.framework.log.ILogger; 060 import org.deegree.framework.log.LoggerFactory; 061 import org.deegree.framework.xml.NamespaceContext; 062 import org.deegree.framework.xml.XMLParsingException; 063 import org.deegree.framework.xml.XMLTools; 064 import org.deegree.ogcbase.CommonNamespaces; 065 import org.w3c.dom.Document; 066 import org.w3c.dom.Element; 067 import org.w3c.dom.Node; 068 import org.w3c.dom.NodeList; 069 import org.xml.sax.SAXException; 070 071 /** 072 * Handler for all web events. 073 * 074 * @author <a href="mailto:tfriebe@gmx.net">Torsten Friebe</a> 075 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 076 * @author last edited by: $Author: mays$ 077 * 078 * @version $Revision: 18195 $, $Date: 21.08.2008 19:19:59$ 079 */ 080 public class ApplicationHandler implements WebListener { 081 082 private static final ILogger LOG = LoggerFactory.getLogger( ApplicationHandler.class ); 083 084 private static final HashMap<String, Class<?>> handler = new HashMap<String, Class<?>>(); 085 086 private static final HashMap<String, String> handlerNext = new HashMap<String, String>(); 087 088 private static final HashMap<String, String> handlerANext = new HashMap<String, String>(); 089 090 private static final HashMap<String, List<ParameterValueIm>> handlerParam = new HashMap<String, List<ParameterValueIm>>(); 091 092 private static final String EVENT = "event"; 093 094 private static final String NAME = "name"; 095 096 private static final String CLASS = "class"; 097 098 private static final String NEXT = "next"; 099 100 private static final String ALTERNATIVENEXT = "alternativeNext"; 101 102 /** 103 * Creates a new ApplicationHandler object. 104 * 105 * @param configFile 106 * @throws Exception 107 */ 108 public ApplicationHandler( String configFile ) throws Exception { 109 ApplicationHandler.initHandler( configFile ); 110 } 111 112 /** 113 * Handles all web action events. Calls the specified listener using the mapping defined in control.xml file. 114 * 115 * @param e 116 * the action event generated out of the incoming http POST event. 117 */ 118 public void actionPerformed( FormEvent e ) { 119 Object source = e.getSource(); 120 121 if ( source instanceof HttpServletRequest ) { 122 HttpServletRequest request = (HttpServletRequest) source; 123 124 String actionName = request.getParameter( "action" ); 125 LOG.logDebug( "Actionname: " + actionName ); 126 if ( actionName != null ) { 127 // handle simple KVP encoded request 128 try { 129 if ( "version".equalsIgnoreCase( actionName ) ) { 130 this.showVersion( request ); 131 } else { 132 try { 133 this.delegateToHelper( actionName, e ); 134 } catch ( Exception ex ) { 135 ex.printStackTrace(); 136 LOG.logError( "Action " + actionName + " is unknown!" ); 137 } 138 } 139 } catch ( Exception ex ) { 140 request.setAttribute( "next", "error.jsp" ); 141 request.setAttribute( "javax.servlet.jsp.jspException", ex ); 142 } 143 } else { 144 // handle RPC encoded request 145 try { 146 RPCMethodCall mc = getMethodCall( request ); 147 e = new RPCWebEvent( e, mc ); 148 this.delegateToHelper( mc.getMethodName(), e ); 149 } catch ( RPCException re ) { 150 re.printStackTrace(); 151 request.setAttribute( "next", "error.jsp" ); 152 request.setAttribute( "javax.servlet.jsp.jspException", re ); 153 } catch ( Exception ee ) { 154 ee.printStackTrace(); 155 request.setAttribute( "next", "error.jsp" ); 156 request.setAttribute( "javax.servlet.jsp.jspException", ee ); 157 } 158 } 159 } 160 } 161 162 /** 163 * extracts the RPC method call from the 164 * 165 * @param request 166 * @return the RPCMethodCall 167 * @throws RPCException 168 */ 169 private RPCMethodCall getMethodCall( ServletRequest request ) 170 throws RPCException { 171 172 String s = request.getParameter( "rpc" ); 173 174 try { 175 if ( s == null ) { 176 StringBuffer sb = new StringBuffer( 1000 ); 177 try { 178 BufferedReader br = request.getReader(); 179 String line = null; 180 while ( ( line = br.readLine() ) != null ) { 181 sb.append( line ); 182 } 183 br.close(); 184 } catch ( Exception e ) { 185 throw new RPCException( "Error reading stream from servlet\n" + e.toString() ); 186 } 187 188 s = sb.toString(); 189 LOG.logDebug( "found first (perhaps double) encoded String: " + s ); 190 s = URLDecoder.decode( s, getSystemCharset() ); 191 String[] splitter = s.split( " \t<>" ); 192 if ( splitter.length == 1 ) { 193 s = URLDecoder.decode( s, getSystemCharset() ); 194 LOG.logDebug( "Decoding a second time: " + s ); 195 } 196 197 int pos1 = s.indexOf( "<methodCall>" ); 198 int pos2 = s.indexOf( "</methodCall>" ); 199 if ( pos1 < 0 ) { 200 throw new RPCException( "request doesn't contain a RPC methodCall" ); 201 } 202 s = s.substring( pos1, pos2 + 13 ); 203 } else { 204 s = URLDecoder.decode( s, Charset.defaultCharset().displayName() ); 205 } 206 } catch ( Exception e ) { 207 e.printStackTrace(); 208 throw new RPCException( e.toString() ); 209 } 210 LOG.logDebug( "RPC: " + s ); 211 212 return RPCFactory.createRPCMethodCall( new StringReader( s ) ); 213 214 } 215 216 /** 217 * 218 * 219 * @param action 220 * @param e 221 * 222 * @throws Exception 223 */ 224 protected void delegateToHelper( String action, FormEvent e ) 225 throws Exception { 226 action = action.trim(); 227 Class<?> cls = ApplicationHandler.handler.get( action ); 228 AbstractListener helper = (AbstractListener) cls.newInstance(); 229 helper.setNextPage( handlerNext.get( action ) ); 230 helper.setDefaultNextPage( handlerNext.get( action ) ); 231 helper.setAlternativeNextPage( handlerANext.get( action ) ); 232 helper.setInitParameterList( handlerParam.get( action ) ); 233 helper.handle( e ); 234 } 235 236 /** 237 * 238 * 239 * @param request 240 */ 241 protected void showVersion( ServletRequest request ) { 242 request.setAttribute( "next", "snoopy.jsp" ); 243 } 244 245 /** 246 * 247 * 248 * @param configFile 249 * 250 * @throws IOException 251 * @throws MalformedURLException 252 * @throws SAXException 253 */ 254 private static void initHandler( String configFile ) 255 throws IOException, MalformedURLException, SAXException { 256 LOG.logInfo( "Reading event handler configuration file:" + configFile ); 257 /* 258 * Read resource into Document... 259 */ 260 URL url = new File( configFile ).toURL(); 261 Reader reader = new InputStreamReader( url.openStream() ); 262 Document doc = XMLTools.parse( reader ); 263 /* 264 * Read and create page elements 265 */ 266 NodeList nodes = doc.getElementsByTagName( EVENT ); 267 268 for ( int i = 0; i < nodes.getLength(); i++ ) { 269 String name = XMLTools.getAttrValue( nodes.item( i ), null, NAME, null ); 270 String cls = XMLTools.getAttrValue( nodes.item( i ), null, CLASS, null ); 271 String nextPage = XMLTools.getAttrValue( nodes.item( i ), null, NEXT, null ); 272 String anextPage = XMLTools.getAttrValue( nodes.item( i ), null, ALTERNATIVENEXT, null ); 273 274 if ( anextPage == null ) { 275 anextPage = nextPage; 276 } 277 278 Class<?> clscls = null; 279 try { 280 clscls = Class.forName( cls ); 281 handler.put( name.trim(), clscls ); 282 handlerNext.put( name.trim(), nextPage ); 283 handlerANext.put( name.trim(), anextPage ); 284 List<ParameterValueIm> pvList = parseParameters( nodes.item( i ) ); 285 handlerParam.put( name.trim(), pvList ); 286 LOG.logInfo( "Handler '" + clscls + "' bound to event '" + name + "'" ); 287 } catch ( Exception ex ) { 288 ex.printStackTrace(); 289 LOG.logError( "No handler '" + cls + "' specified for event '" + name + "'", ex ); 290 throw new SAXException( "No handler class specified for event:" + name + " " + cls + "\n" + ex ); 291 } 292 } 293 } 294 295 /** 296 * several parameters can be passed to each Listener by adding 297 * 298 * <pre> 299 * <parameter> 300 * <name>aName</name> 301 * <value>aValue</value> 302 * </parameter> 303 * </pre> 304 * 305 * sections to the corresponding <event> element. 306 * 307 * @param node 308 * @return a List of ParameterValueIm 309 * @throws XMLParsingException 310 */ 311 private static List<ParameterValueIm> parseParameters( Node node ) 312 throws XMLParsingException { 313 314 NamespaceContext nsc = CommonNamespaces.getNamespaceContext(); 315 List<Node> nodes = XMLTools.getNodes( node, "parameter", nsc ); 316 List<ParameterValueIm> pvs = new ArrayList<ParameterValueIm>(); 317 for ( int i = 0; i < nodes.size(); i++ ) { 318 Element element = (Element) nodes.get( i ); 319 String name = XMLTools.getRequiredNodeAsString( element, "name", nsc ); 320 String value = XMLTools.getRequiredNodeAsString( element, "value", nsc ); 321 GeneralOperationParameterIm descriptor = new GeneralOperationParameterIm( name, null, 1, 1 ); 322 pvs.add( new ParameterValueIm( descriptor, value ) ); 323 } 324 325 return pvs; 326 } 327 328 }