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