    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/portal/standard/context/control/ContextSwitchListener.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
    037    package org.deegree.portal.standard.context.control;
    038
    039    import java.io.File;
    040    import java.io.StringWriter;
    041    import java.net.MalformedURLException;
    042    import java.net.URL;
    043    import java.util.List;
    044
    045    import javax.servlet.http.HttpServletRequest;
    046    import javax.servlet.http.HttpSession;
    047
    048    import org.deegree.enterprise.control.FormEvent;
    049    import org.deegree.enterprise.control.RPCMember;
    050    import org.deegree.enterprise.control.RPCMethodCall;
    051    import org.deegree.enterprise.control.RPCParameter;
    052    import org.deegree.enterprise.control.RPCStruct;
    053    import org.deegree.enterprise.control.RPCUtils;
    054    import org.deegree.enterprise.control.RPCWebEvent;
    055    import org.deegree.framework.log.ILogger;
    056    import org.deegree.framework.log.LoggerFactory;
    057    import org.deegree.framework.util.StringTools;
    058    import org.deegree.framework.xml.NamespaceContext;
    059    import org.deegree.framework.xml.XMLFragment;
    060    import org.deegree.framework.xml.XMLTools;
    061    import org.deegree.framework.xml.XSLTDocument;
    062    import org.deegree.i18n.Messages;
    063    import org.deegree.model.spatialschema.Envelope;
    064    import org.deegree.ogcbase.CommonNamespaces;
    065    import org.deegree.portal.Constants;
    066    import org.deegree.portal.context.ViewContext;
    067    import org.deegree.portal.context.WebMapContextFactory;
    068    import org.deegree.portal.context.XMLFactory;
    069    import org.w3c.dom.Node;
    070
    071    /**
    072     * This class handles switch of map contexts. The basic logic is (1) receiving an rpc request with a context name (xml)
    073     * and, possibly, a bounding box, (2) transforming this xml using a provided xsl, and (3) forwarding the result back to
    074     * the browser. <br/>
    075     * Most of the action takes place in <code>doTransformContext</code>, and is delegated to the
    076     * <code>ContextTransformer</code>.<br/>
    077     * In order to perform the transformation from a context xml to a html, a xslt is provided. This is per default called
    078     * <code>context2HTML.xsl</code> (see the class member <code>DEFAULT_CTXT2HTML</code>) and should be put under
    079     * <code>${context-home}/WEB-INF/xml/</code>. <br/>
    080     *
    081     * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
    082     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    083     * @author last edited by: $Author: apoth $
    084     *
    085     * @version $Revision: 21693 $, $Date: 2010-01-03 15:07:54 +0100 (So, 03. Jan 2010) $
    086     */
    087    public class ContextSwitchListener extends AbstractContextListener {
    088
    089        private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
    090
    091        private static final ILogger LOG = LoggerFactory.getLogger( ContextSwitchListener.class );
    092
    093        /**
    094         * A <code>String</code> used as a key value for the new html (of the client). This key is used in the JSP which
    095         * output the new(-ly transformed html.
    096         */
    097        public static final String NEW_CONTEXT_HTML = "NEW_CONTEXT_HTML";
    098
    099        /**
    100         * A <code>String</code> defining the name of the xsl file that defines the transformation from a context to html.
    101         * This must be placed, together with the map context xml and helper xsl files, under
    102         * <code>${context-home}/WEB-INF/conf/igeoportal/</code>.
    103         */
    104        protected URL ctxt2html;
    105
    106        /**
    107         * script to transform a standard WMC document into a deegree WMC
    108         */
    109        protected static final String WEBMAPCTXT2HTML = "WEB-INF/conf/igeoportal/defaultcontext.xsl";
    110
    111        /*
    112         * (non-Javadoc)
    113         *
    114         * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent)
    115         */
    116        @Override
    117        public void actionPerformed( FormEvent event ) {
    118
    119            RPCMethodCall mc = ( (RPCWebEvent) event ).getRPCMethodCall();
    120            RPCParameter[] pars = mc.getParameters();
    121            RPCStruct struct = (RPCStruct) pars[0].getValue();
    122
    123            // get map context value
    124            String curContxt = RPCUtils.getRpcPropertyAsString( struct, "mapContext" );
    125
    126            // now get bbox
    127            Envelope bbox = null;
    128            RPCMember rpcStruct = struct.getMember( Constants.RPC_BBOX );
    129            if ( rpcStruct != null ) {
    130                RPCStruct bboxStruct = (RPCStruct) rpcStruct.getValue();
    131                bbox = extractBBox( bboxStruct, null );
    132            }
    133
    134            // get the servlet path using the session
    135            HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession();
    136
    137            // path to context dir
    138            String path2Dir = getHomePath();
    139
    140            // context and xsl files
    141            String mapContext = "file://" + path2Dir + "WEB-INF/conf/igeoportal/" + curContxt;
    142
    143            String newHtml = null;
    144            String sid = null;
    145            try {
    146                // read session ID trying different possible sources
    147                sid = readSessionID( struct );
    148
    149                // ContextSwitchLister.actionPerformed is the first action that
    150                // will be performed if a user enter iGeoPortal. So store the
    151                // users sessionID into his HTTP session for futher usage
    152                session.setAttribute( "SESSIONID", sid );
    153                // if no sessionID is available the context will be read as
    154                // anonymous user which will cause that layers assigned to a
    155                // authorized user may will not be parsed correctly
    156                XMLFragment xml = getContext( mapContext, bbox, sid );
    157                newHtml = doTransformContext( xml );
    158            } catch ( Exception e ) {
    159                LOG.logError( e.getMessage(), e );
    160                gotoErrorPage( StringTools.stackTraceToString( e ) );
    161                return;
    162            }
    163
    164            session.setAttribute( NEW_CONTEXT_HTML, newHtml );
    165
    166            // need to keep a reference to the last context...
    167            // often used when changing/saving the shown context
    168            try {
    169                writeContextToSession( mapContext, sid );
    170            } catch ( Exception e ) {
    171                LOG.logError( e.getMessage(), e );
    172                gotoErrorPage( StringTools.stackTraceToString( e ) );
    173            }
    174
    175            getRequest().setAttribute( "SESSIONID", sid );
    176        }
    177
    178        /**
    179         * writes the context the user choosed to the users session. It can be accessed using
    180         * <tt>Constants.CURRENTMAPCONTEXT</tt> key value
    181         *
    182         * @param context
    183         * @param sessionID
    184         * @throws Exception
    185         */
    186        protected void writeContextToSession( String context, String sessionID )
    187                                throws Exception {
    188            URL ctxtUrl = new URL( context );
    189            ViewContext vc = WebMapContextFactory.createViewContext( ctxtUrl, null, sessionID );
    190            HttpSession session = ( (HttpServletRequest) getRequest() ).getSession();
    191            session.setAttribute( Constants.CURRENTMAPCONTEXT, vc );
    192        }
    193
    194        /**
    195         * returns the context to be used as a String
    196         *
    197         * @param context
    198         * @param bbox
    199         * @param sessionID
    200         * @return the context as String
    201         * @throws Exception
    202         */
    203        protected XMLFragment getContext( String context, Envelope bbox, String sessionID )
    204                                throws Exception {
    205
    206            XMLFragment xml = new XMLFragment();
    207            try {
    208                LOG.logInfo( "reading context: " + context );
    209                URL ctxtUrl = new URL( context );
    210
    211                ViewContext vc = WebMapContextFactory.createViewContext( ctxtUrl, null, sessionID );
    212                if ( bbox != null ) {
    213                    changeBBox( vc, bbox );
    214                }
    215
    216                ctxt2html = vc.getGeneral().getExtension().getXslt();
    217
    218                xml = XMLFactory.export( vc );
    219
    220                // if at least one element is present we have a deegree Web Map Context
    221                // document; otherwise we have a standard Web Map Context document that
    222                // must be transformed into a deegree WMC document
    223                List<Node> nl = XMLTools.getNodes( xml.getRootElement().getOwnerDocument(),
    224                                                   "cntxt:ViewContext/cntxt:General/cntxt:Extension/dgcntxt:IOSettings",
    225                                                   nsContext );
    226                if ( nl.size() == 0 ) {
    227                    xml = transformToDeegreeContext( xml );
    228                }
    229            } catch ( Exception e ) {
    230                throw e;
    231            }
    232
    233            return xml;
    234        }
    235
    236        /**
    237         * transforms a standard Web Map Context document to a deegree Web Map Context document
    238         *
    239         * @param xml
    240         * @return the transformed xml
    241         * @throws Exception
    242         */
    243        private XMLFragment transformToDeegreeContext( XMLFragment xml )
    244                                throws Exception {
    245
    246            String xslFilename = getHomePath() + WEBMAPCTXT2HTML;
    247            File file = new File( xslFilename );
    248            XSLTDocument xslt = new XSLTDocument();
    249            xslt.load( file.toURL() );
    250            xml = xslt.transform( xml );
    251
    252            return xml;
    253        }
    254
    255        /**
    256         * Transforms the context pointed to by <code>xml</code> into html using <code>xsl</code>
    257         *
    258         * @param xml
    259         *            the context xml
    260         * @return the transformed context
    261         */
    262        protected String doTransformContext( XMLFragment xml ) {
    263
    264            StringWriter sw = new StringWriter( 60000 );
    265            try {
    266                XSLTDocument xslt = new XSLTDocument();
    267                xslt.load( ctxt2html );
    268                xml = xslt.transform( xml );
    269                xml.write( sw );
    270            } catch ( MalformedURLException e ) {
    271                LOG.logError( e.getMessage(), e );
    272                gotoErrorPage( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_CREATE_URL", e.getMessage() ) );
    273
    274            } catch ( Exception e ) {
    275                LOG.logError( e.getMessage(), e );
    276                gotoErrorPage( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_TRANSFORM_CNTXT", e.getMessage() ) );
    277            }
    278            return sw.toString();
    279        }
    280
    281    }