001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/context/control/AbstractContextListener.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.portal.standard.context.control; 037 038 import java.io.IOException; 039 import java.io.StringWriter; 040 import java.net.MalformedURLException; 041 import java.net.URL; 042 import java.util.ArrayList; 043 044 import javax.servlet.http.HttpServletRequest; 045 import javax.servlet.http.HttpSession; 046 import javax.xml.transform.TransformerException; 047 048 import org.apache.commons.httpclient.HttpClient; 049 import org.apache.commons.httpclient.methods.GetMethod; 050 import org.deegree.enterprise.WebUtils; 051 import org.deegree.enterprise.control.AbstractListener; 052 import org.deegree.enterprise.control.RPCMember; 053 import org.deegree.enterprise.control.RPCMethodCall; 054 import org.deegree.enterprise.control.RPCParameter; 055 import org.deegree.enterprise.control.RPCStruct; 056 import org.deegree.enterprise.control.RPCUtils; 057 import org.deegree.enterprise.control.RPCWebEvent; 058 import org.deegree.framework.log.ILogger; 059 import org.deegree.framework.log.LoggerFactory; 060 import org.deegree.framework.util.StringTools; 061 import org.deegree.framework.xml.NamespaceContext; 062 import org.deegree.framework.xml.XMLFragment; 063 import org.deegree.framework.xml.XMLParsingException; 064 import org.deegree.framework.xml.XMLTools; 065 import org.deegree.framework.xml.XSLTDocument; 066 import org.deegree.i18n.Messages; 067 import org.deegree.model.crs.CoordinateSystem; 068 import org.deegree.model.spatialschema.Envelope; 069 import org.deegree.model.spatialschema.GeometryFactory; 070 import org.deegree.model.spatialschema.Point; 071 import org.deegree.ogcbase.BaseURL; 072 import org.deegree.ogcbase.CommonNamespaces; 073 import org.deegree.ogcwebservices.OWSUtils; 074 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 075 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 076 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 077 import org.deegree.portal.Constants; 078 import org.deegree.portal.PortalException; 079 import org.deegree.portal.context.ContextException; 080 import org.deegree.portal.context.General; 081 import org.deegree.portal.context.GeneralExtension; 082 import org.deegree.portal.context.Layer; 083 import org.deegree.portal.context.LayerList; 084 import org.deegree.portal.context.Server; 085 import org.deegree.portal.context.ViewContext; 086 import org.xml.sax.SAXException; 087 088 /** 089 * This exception shall be thrown when a session(ID) will be used that has been expired. 090 * 091 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 092 * @author last edited by: $Author: jmays $ 093 * 094 * @version $Revision: 19116 $, $Date: 2009-08-14 11:48:50 +0200 (Fr, 14. Aug 2009) $ 095 */ 096 abstract public class AbstractContextListener extends AbstractListener { 097 098 private static ILogger LOG = LoggerFactory.getLogger( AbstractContextListener.class ); 099 100 private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 101 102 /** 103 * gets the user name assigned to the passed session ID from an authentication service. If no user is assigned to 104 * the session ID <tt>null</tt> will be returned. If the session is closed or expired an exception will be thrown 105 * 106 * @param sessionId 107 * @return name of the user assigned to the passed session ID 108 * @throws XMLParsingException 109 * @throws SAXException 110 * @throws IOException 111 */ 112 protected String getUserName( String sessionId ) 113 throws XMLParsingException, IOException, SAXException { 114 115 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true ); 116 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); 117 if ( vc == null ) { 118 return null; 119 } 120 GeneralExtension ge = vc.getGeneral().getExtension(); 121 String userName = null; 122 if ( sessionId != null && ge.getAuthentificationSettings() != null ) { 123 LOG.logDebug( "try getting user from WAS/sessionID" ); 124 BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL(); 125 String url = OWSUtils.validateHTTPGetBaseURL( baseUrl.getOnlineResource().toExternalForm() ); 126 StringBuffer sb = new StringBuffer( url ); 127 sb.append( "request=DescribeUser&SESSIONID=" ).append( sessionId ); 128 129 XMLFragment xml = new XMLFragment(); 130 xml.load( new URL( sb.toString() ) ); 131 132 userName = XMLTools.getRequiredNodeAsString( xml.getRootElement(), "/User/UserName", nsContext ); 133 } else { 134 LOG.logDebug( "try getting user from getUserPrincipal()" ); 135 if ( ( (HttpServletRequest) getRequest() ).getUserPrincipal() != null ) { 136 userName = ( (HttpServletRequest) getRequest() ).getUserPrincipal().getName(); 137 if ( userName.indexOf( "\\" ) > 1 ) { 138 String[] us = StringTools.toArray( userName, "\\", false ); 139 userName = us[us.length - 1]; 140 } 141 } 142 } 143 LOG.logDebug( "userName: " + userName ); 144 return userName; 145 } 146 147 /** 148 * gets the user password assigned to the passed session ID from a authentification service. If no user is assigned 149 * to the session ID <tt>null</tt> will be returned. If the session is closed or expired an exception will be 150 * thrown 151 * 152 * @param sessionId 153 * @return password of the user assigned to the passed session ID 154 */ 155 protected String getUserPassword( String sessionId ) 156 throws XMLParsingException, IOException, SAXException, PortalException { 157 158 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true ); 159 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); 160 if ( vc == null ) { 161 return null; 162 } 163 GeneralExtension ge = vc.getGeneral().getExtension(); 164 String userPassword = null; 165 if ( sessionId != null && ge.getAuthentificationSettings() != null ) { 166 LOG.logDebug( "try getting user from WAS/sessionID" ); 167 BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL(); 168 String url = OWSUtils.validateHTTPGetBaseURL( baseUrl.getOnlineResource().toExternalForm() ); 169 StringBuffer sb = new StringBuffer( url ); 170 sb.append( "request=DescribeUser&SESSIONID=" ).append( sessionId ); 171 172 XMLFragment xml = new XMLFragment(); 173 xml.load( new URL( sb.toString() ) ); 174 175 LOG.logDebug( xml.getAsPrettyString() ); 176 userPassword = XMLTools.getRequiredNodeAsString( xml.getRootElement(), "/User/Password", nsContext ); 177 } else { 178 throw new PortalException( "The session ID is null and thus the user password can not be extracted" ); 179 } 180 LOG.logDebug( "Password: " + userPassword ); 181 return userPassword; 182 } 183 184 /** 185 * reads the users session ID.<br> 186 * first the PRC will be parsed for a 'sessionID' element. If not present the sessionID will be read from the users 187 * session. If even the user's HTTP session does not contain a sessionID, it will be tried to get it from the WAS 188 * registered to the current context. If no WAS available <code>null</code> will be returned. 189 * 190 * @param struct 191 * @return the users session id 192 * @throws IOException 193 * @throws SAXException 194 * @throws XMLParsingException 195 */ 196 protected String readSessionID( RPCStruct struct ) 197 throws XMLParsingException, SAXException, IOException { 198 String sid = RPCUtils.getRpcPropertyAsString( struct, "sessionID" ); 199 if ( sid == null ) { 200 LOG.logDebug( "try getting sessionID from HTTP session" ); 201 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession(); 202 sid = (String) session.getAttribute( "SESSIONID" ); 203 } 204 if ( sid == null ) { 205 // try get SessionID from WAS if user name is available 206 // in this case it is assumed that a user's name can be determined 207 // evaluating the requests userPrincipal that will be available if 208 // the user has been logged in to the the server (or network) 209 String userName = getUserName( null ); 210 if ( userName != null ) { 211 LOG.logDebug( "try getting sessionID by authorizing current user: " + userName ); 212 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true ); 213 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); 214 GeneralExtension ge = vc.getGeneral().getExtension(); 215 if ( ge.getAuthentificationSettings() != null ) { 216 BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL(); 217 StringBuffer sb = new StringBuffer( 500 ); 218 String addr = baseUrl.getOnlineResource().toExternalForm(); 219 sb.append( OWSUtils.validateHTTPGetBaseURL( addr ) ); 220 sb.append( "SERVICE=WAS&VERSION=1.0.0&REQUEST=GetSession&" ); 221 sb.append( "AUTHMETHOD=urn:x-gdi-nrw:authnMethod:1.0:password&CREDENTIALS=" ); 222 sb.append( userName ); 223 LOG.logDebug( "authenticat user: ", sb.toString() ); 224 HttpClient client = new HttpClient(); 225 client = WebUtils.enableProxyUsage( client, baseUrl.getOnlineResource() ); 226 GetMethod meth = new GetMethod( sb.toString() ); 227 client.executeMethod( meth ); 228 sid = meth.getResponseBodyAsString(); 229 session.setAttribute( "SESSIONID", sid ); 230 } 231 } 232 } 233 LOG.logDebug( "sessionID: " + sid ); 234 return sid; 235 } 236 237 /** 238 * Convenience method to extract the boundig box from an rpc fragment. 239 * 240 * @param bboxStruct 241 * the <code>RPCStruct</code> containing the bounding box. For example, 242 * <code><member><name>boundingBox</name>etc...</code>. 243 * @param crs 244 * a coordinate system value, may be null. 245 * @return an envelope with the boundaries defined in the rpc structure 246 */ 247 protected Envelope extractBBox( RPCStruct bboxStruct, CoordinateSystem crs ) { 248 249 Double minx = (Double) bboxStruct.getMember( Constants.RPC_BBOXMINX ).getValue(); 250 Double miny = (Double) bboxStruct.getMember( Constants.RPC_BBOXMINY ).getValue(); 251 Double maxx = (Double) bboxStruct.getMember( Constants.RPC_BBOXMAXX ).getValue(); 252 Double maxy = (Double) bboxStruct.getMember( Constants.RPC_BBOXMAXY ).getValue(); 253 254 Envelope bbox = GeometryFactory.createEnvelope( minx.doubleValue(), miny.doubleValue(), maxx.doubleValue(), 255 maxy.doubleValue(), crs ); 256 return bbox; 257 } 258 259 /** 260 * This method is kept for downward compatibility of the API. Do not use it any more! 261 * 262 * @deprecated use extractBBox( RPCStruct, CoordinateSystem ) instead. 263 * @param bboxStruct 264 * the <code>RPCStruct</code> containing the bounding box. For example, 265 * <code><member><name>boundingBox</name>etc...</code>. 266 * @return an envelope with the boundaries defined in the rpc structure 267 */ 268 @Deprecated 269 protected Envelope extractBBox( RPCStruct bboxStruct ) { 270 return extractBBox( bboxStruct, null ); 271 } 272 273 /** 274 * changes the bounding box of a given view context 275 * 276 * @param vc 277 * the view context to be changed 278 * @param bbox 279 * the new bounding box 280 * @throws PortalException 281 */ 282 public static final void changeBBox( ViewContext vc, Envelope bbox ) 283 throws PortalException { 284 General gen = vc.getGeneral(); 285 286 CoordinateSystem cs = gen.getBoundingBox()[0].getCoordinateSystem(); 287 Point[] p = new Point[] { GeometryFactory.createPoint( bbox.getMin(), cs ), 288 GeometryFactory.createPoint( bbox.getMax(), cs ) }; 289 try { 290 gen.setBoundingBox( p ); 291 } catch ( ContextException e ) { 292 LOG.logError( e.getMessage(), e ); 293 throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_SET_BBOX" ) ); 294 } 295 } 296 297 /** 298 * changes the layer list of the ViewContext vc according to the information contained in the rpcLayerList 299 * 300 * @param vc 301 * The original ViewContext where the changes will be applied to 302 * @param rpcLayerList 303 * the current layerlist 304 * @throws PortalException 305 */ 306 protected void changeLayerList( ViewContext vc, RPCMember[] rpcLayerList ) 307 throws PortalException { 308 LayerList layerList = vc.getLayerList(); 309 ArrayList<Layer> nLayers = new ArrayList<Layer>( rpcLayerList.length ); 310 311 // this is needed to keep layer order 312 // order is correct in rpc call JavaScript) but get lost in translation... 313 for ( int i = 0; i < rpcLayerList.length; i++ ) { 314 String[] v = StringTools.toArray( (String) rpcLayerList[i].getValue(), "|", false ); 315 String n = rpcLayerList[i].getName(); 316 317 String title = n; 318 if ( v.length > 5 ) { 319 // this check is necessary, in order to not break running iGeoPortal instances 320 title = v[5]; 321 } 322 boolean isQueryable = false; 323 if ( v.length > 6 ) { 324 // JM: this check is necessary, in order to not break running iGeoPortal instances 325 isQueryable = v[6].equalsIgnoreCase( "true" ); 326 } 327 328 boolean isVisible = Boolean.valueOf( v[0] ).booleanValue(); 329 Layer l = layerList.getLayer( n, null ); 330 if ( l != null ) { 331 // needed to reconstruct new layer order 332 // otherwise layer order is still from original context 333 l.setHidden( !isVisible ); 334 } else { 335 336 if ( layerList.getLayers().length == 0 ) { 337 // FIXME is this Exception Correct 338 throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_EMPTY_LAYERLIST" ) ); 339 } 340 341 Layer p = layerList.getLayers()[0]; 342 // a new layer must be created because it is not prsent 343 // in the current context. This is the case if the client 344 // has loaded an additional WMS 345 String[] tmp = StringTools.toArray( v[2], " ", false ); 346 try { 347 v[4] = OWSUtils.validateHTTPGetBaseURL( v[4] ); 348 WMSCapabilitiesDocument doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( new URL( 349 v[4] 350 + "request=GetCapabilities&service=WMS" ) ); 351 OGCCapabilities capa = doc.parseCapabilities(); 352 Server server = new Server( v[3], tmp[1], tmp[0], new URL( v[4] ), capa ); 353 // l = new Layer( server, n, title, "", p.getSrs(), null, null, p.getFormatList(), p.getStyleList(), 354 // isQueryable, !isVisible, null ); 355 l = new Layer( server, n, title, "", p.getSrs(), p.getDataURL(), p.getMetadataURL(), 356 p.getFormatList(), p.getStyleList(), isQueryable, !isVisible, p.getExtension() ); 357 } catch ( Exception e ) { 358 throw new PortalException( StringTools.stackTraceToString( e ) ); 359 } 360 } 361 nLayers.add( l ); 362 } 363 try { 364 nLayers.trimToSize(); 365 Layer[] ls = new Layer[nLayers.size()]; 366 ls = nLayers.toArray( ls ); 367 vc.setLayerList( new LayerList( ls ) ); 368 } catch ( ContextException e ) { 369 throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_SET_LAYERLIST", 370 StringTools.stackTraceToString( e.getStackTrace() ) ) ); 371 } 372 } 373 374 /** 375 * This function takes in a XmlFragment and transforms it to a html map context 376 * 377 * @param xml 378 * xmlFragment to transform 379 * @param xsl 380 * xsl file used to transform 381 * @return html representing the mapContext 382 * @throws TransformerException 383 * @throws SAXException 384 * @throws IOException 385 * @throws MalformedURLException 386 */ 387 protected String transformToHtmlMapContext( XMLFragment xml, String xsl ) 388 throws TransformerException, MalformedURLException, IOException, SAXException { 389 390 XSLTDocument xslt = new XSLTDocument(); 391 StringWriter sw = new StringWriter( 30000 ); 392 393 xslt.load( new URL( xsl ) ); 394 xml = xslt.transform( xml ); 395 xml.write( sw ); 396 397 return sw.toString(); 398 } 399 400 /** 401 * Extracts the parameters from the method call element within the passed rpcEvent. 402 * 403 * @param rpcEvent 404 * @return Returns the parameters as array of <code>RPCParameter</code>. 405 * @throws PortalException 406 */ 407 protected RPCParameter[] extractRPCParameters( RPCWebEvent rpcEvent ) 408 throws PortalException { 409 RPCParameter[] params; 410 try { 411 RPCMethodCall mc = rpcEvent.getRPCMethodCall(); 412 params = mc.getParameters(); 413 } catch ( Exception e ) { 414 throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_EXTRACT_PARAM_RPC", e.getMessage() ) ); 415 } 416 return params; 417 } 418 419 /** 420 * Extracts the <code>RPCStruct</code> from the indicated parameter in the params element of the passed 421 * <code>RPCWebEvent</code>. 422 * 423 * @param rpcEvent 424 * The RPCWebEvent, that contains the RPCStruct to extract. 425 * @param index 426 * The index of the parameter from which to extract the RPCStruct (starting with 0). 427 * @return Returns the <code>RPCStruct</code> from the indicated params element. 428 * @throws PortalException 429 */ 430 protected RPCStruct extractRPCStruct( RPCWebEvent rpcEvent, int index ) 431 throws PortalException { 432 RPCStruct rpcStruct; 433 try { 434 RPCParameter[] params = extractRPCParameters( rpcEvent ); 435 rpcStruct = (RPCStruct) params[index].getValue(); 436 } catch ( Exception e ) { 437 throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_EXTRACT_STRUCT_RPC", e.getMessage() ) ); 438 } 439 return rpcStruct; 440 } 441 442 }