001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/enterprise/control/ApplicationHandler.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 package org.deegree.enterprise.control; 045 046 import java.io.BufferedReader; 047 import java.io.File; 048 import java.io.IOException; 049 import java.io.InputStreamReader; 050 import java.io.Reader; 051 import java.io.StringReader; 052 import java.net.MalformedURLException; 053 import java.net.URL; 054 import java.net.URLDecoder; 055 import java.nio.charset.Charset; 056 import java.util.ArrayList; 057 import java.util.HashMap; 058 import java.util.List; 059 060 import javax.servlet.ServletRequest; 061 import javax.servlet.http.HttpServletRequest; 062 063 import org.deegree.datatypes.parameter.GeneralOperationParameterIm; 064 import org.deegree.datatypes.parameter.ParameterValueIm; 065 import org.deegree.framework.log.ILogger; 066 import org.deegree.framework.log.LoggerFactory; 067 import org.deegree.framework.xml.NamespaceContext; 068 import org.deegree.framework.xml.XMLParsingException; 069 import org.deegree.framework.xml.XMLTools; 070 import org.deegree.ogcbase.CommonNamespaces; 071 import org.w3c.dom.Document; 072 import org.w3c.dom.Element; 073 import org.w3c.dom.Node; 074 import org.w3c.dom.NodeList; 075 import org.xml.sax.SAXException; 076 077 /** 078 * Handler for all web events. 079 * 080 * @author <a href="mailto:tfriebe@gmx.net">Torsten Friebe</a> 081 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 082 * 083 * @version $Revision: $, $Date: 15.10.2007 15:39:10$ 084 */ 085 public class ApplicationHandler implements WebListener { 086 087 private static final ILogger LOG = LoggerFactory.getLogger( ApplicationHandler.class ); 088 089 private static final HashMap<String, Class> handler = new HashMap<String, Class>(); 090 091 private static final HashMap<String, String> handlerNext = new HashMap<String, String>(); 092 093 private static final HashMap<String, String> handlerANext = new HashMap<String, String>(); 094 095 private static final HashMap<String, List<ParameterValueIm>> handlerParam = new HashMap<String, List<ParameterValueIm>>(); 096 097 private static final String EVENT = "event"; 098 099 private static final String NAME = "name"; 100 101 private static final String CLASS = "class"; 102 103 private static final String NEXT = "next"; 104 105 private static final String ALTERNATIVENEXT = "alternativeNext"; 106 107 /** 108 * Creates a new ApplicationHandler object. 109 * 110 * @param configFile 111 * @throws Exception 112 */ 113 public ApplicationHandler( String configFile ) throws Exception { 114 ApplicationHandler.initHandler( configFile ); 115 } 116 117 /** 118 * Handles all web action events. Calls the specified listener using the mapping defined in 119 * control.xml file. 120 * 121 * @param e 122 * the action event generated out of the incoming http POST event. 123 */ 124 public void actionPerformed( FormEvent e ) { 125 Object source = e.getSource(); 126 127 if ( source instanceof HttpServletRequest ) { 128 HttpServletRequest request = (HttpServletRequest) source; 129 130 String actionName = request.getParameter( "action" ); 131 LOG.logDebug( "Actionname: " + actionName ); 132 if ( actionName != null ) { 133 // handle simple KVP encoded request 134 try { 135 if ( "version".equalsIgnoreCase( actionName ) ) { 136 this.showVersion( request ); 137 } else { 138 try { 139 this.delegateToHelper( actionName, e ); 140 } catch ( Exception ex ) { 141 ex.printStackTrace(); 142 LOG.logError( "Action " + actionName + " is unknown!" ); 143 } 144 } 145 } catch ( Exception ex ) { 146 request.setAttribute( "next", "error.jsp" ); 147 request.setAttribute( "javax.servlet.jsp.jspException", ex ); 148 } 149 } else { 150 // handle RPC encoded request 151 try { 152 RPCMethodCall mc = getMethodCall( request ); 153 e = new RPCWebEvent( e, mc ); 154 this.delegateToHelper( mc.getMethodName(), e ); 155 } catch ( RPCException re ) { 156 re.printStackTrace(); 157 request.setAttribute( "next", "error.jsp" ); 158 request.setAttribute( "javax.servlet.jsp.jspException", re ); 159 } catch ( Exception ee ) { 160 ee.printStackTrace(); 161 request.setAttribute( "next", "error.jsp" ); 162 request.setAttribute( "javax.servlet.jsp.jspException", ee ); 163 } 164 } 165 } 166 } 167 168 /** 169 * extracts the RPC method call from the 170 * 171 * @param request 172 * @return the RPCMethodCall 173 * @throws RPCException 174 */ 175 private RPCMethodCall getMethodCall( ServletRequest request ) 176 throws RPCException { 177 178 String s = request.getParameter( "rpc" ); 179 180 try { 181 if ( s == null ) { 182 StringBuffer sb = new StringBuffer( 1000 ); 183 try { 184 BufferedReader br = request.getReader(); 185 String line = null; 186 while ( ( line = br.readLine() ) != null ) { 187 sb.append( line ); 188 } 189 br.close(); 190 } catch ( Exception e ) { 191 throw new RPCException( "Error reading stream from servlet\n" + e.toString() ); 192 } 193 194 s = sb.toString(); 195 LOG.logDebug( "found first (perhaps double) encoded String: " + s ); 196 s = URLDecoder.decode( s, Charset.defaultCharset().name() ); 197 String[] splitter = s.split( " \t<>" ); 198 if( splitter.length == 1 ){ 199 s = URLDecoder.decode( s, Charset.defaultCharset().name() ); 200 LOG.logDebug( "Decoding a second time: " + s ); 201 } 202 203 int pos1 = s.indexOf( "<methodCall>" ); 204 int pos2 = s.indexOf( "</methodCall>" ); 205 if ( pos1 < 0 ) { 206 throw new RPCException( "request doesn't contain a RPC methodCall" ); 207 } 208 s = s.substring( pos1, pos2 + 13 ); 209 } else { 210 s = URLDecoder.decode( s, Charset.defaultCharset().name() ); 211 } 212 } catch ( Exception e ) { 213 e.printStackTrace(); 214 throw new RPCException( e.toString() ); 215 } 216 217 LOG.logDebug( "RPC: " + s ); 218 219 return RPCFactory.createRPCMethodCall( new StringReader( s ) ); 220 221 } 222 223 /** 224 * 225 * 226 * @param action 227 * @param e 228 * 229 * @throws Exception 230 */ 231 protected void delegateToHelper( String action, FormEvent e ) 232 throws Exception { 233 action = action.trim(); 234 Class cls = ApplicationHandler.handler.get( action ); 235 AbstractListener helper = (AbstractListener) cls.newInstance(); 236 helper.setNextPage( handlerNext.get( action ) ); 237 helper.setDefaultNextPage( handlerNext.get( action ) ); 238 helper.setAlternativeNextPage( handlerANext.get( action ) ); 239 helper.setInitParameterList( handlerParam.get( action ) ); 240 helper.handle( e ); 241 } 242 243 /** 244 * 245 * 246 * @param request 247 */ 248 protected void showVersion( ServletRequest request ) { 249 request.setAttribute( "next", "snoopy.jsp" ); 250 } 251 252 /** 253 * 254 * 255 * @param configFile 256 * 257 * @throws IOException 258 * @throws MalformedURLException 259 * @throws SAXException 260 */ 261 private static void initHandler( String configFile ) 262 throws IOException, MalformedURLException, SAXException { 263 LOG.logInfo( "Reading event handler configuration file:" + configFile ); 264 /* 265 * Read resource into Document... 266 */ 267 URL url = new File( configFile ).toURL(); 268 Reader reader = new InputStreamReader( url.openStream() ); 269 Document doc = XMLTools.parse( reader ); 270 /* 271 * Read and create page elements 272 */ 273 NodeList nodes = doc.getElementsByTagName( EVENT ); 274 275 for ( int i = 0; i < nodes.getLength(); i++ ) { 276 String name = XMLTools.getAttrValue( nodes.item( i ), null, NAME, null ); 277 String cls = XMLTools.getAttrValue( nodes.item( i ), null, CLASS, null ); 278 String nextPage = XMLTools.getAttrValue( nodes.item( i ), null, NEXT, null ); 279 String anextPage = XMLTools.getAttrValue( nodes.item( i ), null, ALTERNATIVENEXT, null ); 280 281 if ( anextPage == null ) { 282 anextPage = nextPage; 283 } 284 285 Class clscls = null; 286 try { 287 clscls = Class.forName( cls ); 288 handler.put( name.trim(), clscls ); 289 handlerNext.put( name.trim(), nextPage ); 290 handlerANext.put( name.trim(), anextPage ); 291 List<ParameterValueIm> pvList = parseParameters( nodes.item( i ) ); 292 handlerParam.put( name.trim(), pvList ); 293 LOG.logInfo( "Handler '" + clscls + "' bound to event '" + name + "'" ); 294 } catch ( Exception ex ) { 295 ex.printStackTrace(); 296 LOG.logError( "No handler '" + cls + "' specified for event '" + name + "'", ex ); 297 throw new SAXException( "No handler class specified for event:" + name + " " + cls + "\n" + ex ); 298 } 299 } 300 } 301 302 /** 303 * several parameters can be passed to each Listener by adding 304 * 305 * <pre> 306 * <parameter> 307 * <name>aName</name> 308 * <value>aValue</value> 309 * </parameter> 310 * </pre> 311 * 312 * sections to the corresponding <event> element. 313 * 314 * @param node 315 * @return a List of ParameterValueIm 316 * @throws XMLParsingException 317 */ 318 private static List<ParameterValueIm> parseParameters( Node node ) 319 throws XMLParsingException { 320 321 NamespaceContext nsc = CommonNamespaces.getNamespaceContext(); 322 List nodes = XMLTools.getNodes( node, "parameter", nsc ); 323 List<ParameterValueIm> pvs = new ArrayList<ParameterValueIm>(); 324 for ( int i = 0; i < nodes.size(); i++ ) { 325 Element element = (Element) nodes.get( i ); 326 String name = XMLTools.getRequiredNodeAsString( element, "name", nsc ); 327 String value = XMLTools.getRequiredNodeAsString( element, "value", nsc ); 328 GeneralOperationParameterIm descriptor = new GeneralOperationParameterIm( name, null, 1, 1 ); 329 pvs.add( new ParameterValueIm( descriptor, value ) ); 330 } 331 332 return pvs; 333 } 334 335 }