001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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    }