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 }