    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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         *   &lt;parameter&gt;
    300         *       &lt;name&gt;aName&lt;/name&gt;
    301         *       &lt;value&gt;aValue&lt;/value&gt;
    302         *   &lt;/parameter&gt;
    303         * </pre>
    304         *
    305         * sections to the corresponding &lt;event&gt; 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    }