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 }