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 }