001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/portal/standard/csw/control/OverviewMetadataListener.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.csw.control; 038 039 import java.io.FileNotFoundException; 040 import java.io.IOException; 041 import java.io.Reader; 042 import java.io.StringReader; 043 import java.net.MalformedURLException; 044 import java.net.URL; 045 import java.util.ArrayList; 046 import java.util.HashMap; 047 import java.util.Iterator; 048 import java.util.List; 049 import java.util.Map; 050 051 import javax.servlet.http.HttpServletRequest; 052 import javax.servlet.http.HttpSession; 053 import javax.xml.transform.TransformerException; 054 055 import org.deegree.enterprise.control.FormEvent; 056 import org.deegree.enterprise.control.RPCParameter; 057 import org.deegree.enterprise.control.RPCStruct; 058 import org.deegree.enterprise.control.RPCWebEvent; 059 import org.deegree.framework.log.ILogger; 060 import org.deegree.framework.log.LoggerFactory; 061 import org.deegree.framework.util.CharsetUtils; 062 import org.deegree.framework.xml.DOMPrinter; 063 import org.deegree.framework.xml.XMLFragment; 064 import org.deegree.framework.xml.XMLParsingException; 065 import org.deegree.framework.xml.XMLTools; 066 import org.deegree.i18n.Messages; 067 import org.deegree.ogcbase.CommonNamespaces; 068 import org.deegree.portal.standard.csw.CatalogClientException; 069 import org.deegree.portal.standard.csw.MetadataTransformer; 070 import org.deegree.portal.standard.csw.configuration.CSWClientConfiguration; 071 import org.w3c.dom.Document; 072 import org.w3c.dom.Node; 073 074 /** 075 * A <code>${type_name}</code> class.<br/> TODO class description 076 * 077 * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a> 078 * @author last edited by: $Author: mschneider $ 079 * 080 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 081 */ 082 public class OverviewMetadataListener extends SimpleSearchListener { 083 084 private static final ILogger LOG = LoggerFactory.getLogger( OverviewMetadataListener.class ); 085 086 static final String SESSION_METADATA = "SESSION_METADATA"; 087 088 @Override 089 public void actionPerformed( FormEvent event ) { 090 091 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 092 config = (CSWClientConfiguration) session.getAttribute( Constants.CSW_CLIENT_CONFIGURATION ); 093 094 nsContext = CommonNamespaces.getNamespaceContext(); 095 096 RPCWebEvent rpcEvent = (RPCWebEvent) event; 097 RPCParameter[] params; 098 try { 099 params = extractRPCParameters( rpcEvent ); 100 } catch ( Exception e ) { 101 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_RPC_EVENT", e.getMessage() ) ); 102 LOG.logError( e.getMessage(), e ); 103 return; 104 } 105 106 // get transformation file name 107 String fileName = "csw/metaOverview2html.xsl"; // default value 108 // FIXME replace format with current value 109 String format = "Profiles.ISO19115"; 110 HashMap xslMap = config.getProfileXSL( format ); 111 if ( xslMap != null ) { 112 if ( xslMap.get( "full" ) != null ) { 113 fileName = (String) xslMap.get( "full" ); 114 } 115 } 116 String pathToXslFile = "file:" + getHomePath() + "WEB-INF/conf/igeoportal/" + fileName; 117 LOG.logDebug( "path to xslFile: ", pathToXslFile ); 118 119 if ( params == null || params.length == 0 ) { 120 // get Metadata from the users session 121 session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 122 Object o = session.getAttribute( SESSION_METADATA ); 123 124 if ( o != null ) { 125 try { 126 handleResult( o, pathToXslFile, "overview" ); 127 } catch ( Exception e ) { 128 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_HANDLE_RESULT", e.getMessage() ) ); 129 LOG.logError( e.getMessage() ); 130 return; 131 } 132 } 133 } else { 134 try { 135 validateRequest( rpcEvent ); 136 } catch ( Exception e ) { 137 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_REQ", e.getMessage() ) ); 138 LOG.logError( e.getMessage() ); 139 return; 140 } 141 142 String rpcCatalog; 143 RPCStruct rpcStruct; 144 String rpcFormat; 145 String rpcProtocol; 146 147 try { 148 rpcStruct = extractRPCStruct( rpcEvent, 0 ); 149 rpcCatalog = (String) extractRPCMember( rpcStruct, RPC_CATALOG ); 150 rpcFormat = (String) extractRPCMember( rpcStruct, RPC_FORMAT ); 151 rpcProtocol = (String) extractRPCMember( rpcStruct, Constants.RPC_PROTOCOL ); 152 } catch ( Exception e ) { 153 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_RPC_EVENT", e.getMessage() ) ); 154 LOG.logError( e.getMessage() ); 155 return; 156 } 157 158 // "GetRecordById"-request 159 String req = null; 160 HashMap result = null; 161 try { 162 req = createRequest( rpcStruct, rpcFormat, null ); 163 } catch ( Exception e ) { 164 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_REQ", e.getMessage() ) ); 165 LOG.logError( e.getMessage() ); 166 return; 167 } 168 try { 169 List<String> dataCatalogs = new ArrayList<String>( 1 ); 170 dataCatalogs.add( rpcCatalog ); 171 172 // key = data catalog name; value = csw:GetRecordByIdResponse 173 result = performRequest( rpcProtocol, req, dataCatalogs ); 174 // result is a HashMap that contains only one key-value-pair, 175 // because dataCatalogs contains only one catalog. 176 } catch ( Exception e ) { 177 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_SERVER_ERROR", e.getMessage() ) ); 178 LOG.logError( e.getMessage() ); 179 return; 180 } 181 182 // handle result: take result and transform it to produce html output 183 try { 184 handleResult( result, pathToXslFile, "overview" ); 185 } catch ( Exception e ) { 186 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_HANDLE_RESULT", e.getMessage() ) ); 187 LOG.logError( e.getMessage() ); 188 return; 189 } 190 191 } 192 193 } 194 195 /* 196 * (non-Javadoc) 197 * 198 * @see org.deegree.portal.standard.csw.control.SimpleSearchListener#validateRequest(org.deegree.enterprise.control.RPCWebEvent) 199 */ 200 @Override 201 protected void validateRequest( RPCWebEvent rpcEvent ) 202 throws CatalogClientException { 203 204 RPCParameter[] params = extractRPCParameters( rpcEvent ); 205 if ( params.length != 1 ) { 206 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_WRONG_PARAMS_NUMBER", "1", 207 params.length ) ); 208 } 209 210 RPCStruct struct = extractRPCStruct( rpcEvent, 0 ); 211 212 // validity check for catalog 213 String rpcCatalog = (String) extractRPCMember( struct, RPC_CATALOG ); 214 String[] catalogs = config.getCatalogNames(); 215 boolean containsCatalog = false; 216 for ( int i = 0; i < catalogs.length; i++ ) { 217 if ( catalogs[i].equals( rpcCatalog ) ) { 218 containsCatalog = true; 219 break; 220 } 221 } 222 if ( !containsCatalog ) { 223 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_WRONG_CAT", rpcCatalog ) ); 224 } 225 226 // validity check for format 227 // is requested catalog capable to serve requested metadata format? 228 List formats = config.getCatalogFormats( rpcCatalog ); 229 String rpcFormat = (String) extractRPCMember( struct, RPC_FORMAT ); 230 if ( !formats.contains( rpcFormat ) ) { 231 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_WRONG_FORMAT", rpcCatalog, rpcFormat ) ); 232 } 233 234 // validity check for protocol 235 // is requested catalog reachable through requested protocol? 236 List protocols = config.getCatalogProtocols( rpcCatalog ); 237 String rpcProtocol = (String) extractRPCMember( struct, Constants.RPC_PROTOCOL ); 238 if ( !protocols.contains( rpcProtocol ) ) { 239 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_WRONG_PROTOCOL", rpcCatalog, 240 rpcProtocol ) ); 241 } 242 243 try { 244 struct.getMember( Constants.RPC_IDENTIFIER ).getValue(); 245 } catch ( Exception e ) { 246 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_ID" ) ); 247 } 248 249 // validity check for bounding box values 250 RPCStruct bBox; 251 try { 252 bBox = (RPCStruct) struct.getMember( Constants.RPC_BBOX ).getValue(); 253 } catch ( Exception e ) { 254 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_BBOX" ) ); 255 } 256 double minx, miny, maxx, maxy; 257 try { 258 minx = ( (Double) bBox.getMember( Constants.RPC_BBOXMINX ).getValue() ).doubleValue(); 259 miny = ( (Double) bBox.getMember( Constants.RPC_BBOXMINY ).getValue() ).doubleValue(); 260 maxx = ( (Double) bBox.getMember( Constants.RPC_BBOXMAXX ).getValue() ).doubleValue(); 261 maxy = ( (Double) bBox.getMember( Constants.RPC_BBOXMAXY ).getValue() ).doubleValue(); 262 } catch ( Exception e ) { 263 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_NOT_DECIMAL" ) ); 264 } 265 if ( minx > maxx || miny > maxy ) { 266 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_VALUES" ) ); 267 } 268 } 269 270 // super.createRequest(); 271 272 // super.performeRequest(); 273 274 /** 275 * @param result 276 * @param pathToXslFile 277 * e.g. file://$iGeoPortal_home$/WEB-INF/conf/igeoportal/metaOverview2html.xsl 278 * @param metaVersion 279 * e.g. overview, detailed 280 * @throws XMLParsingException 281 * @throws CatalogClientException 282 * @throws TransformerException 283 * @throws IOException 284 */ 285 protected void handleResult( Object result, String pathToXslFile, String metaVersion ) 286 throws XMLParsingException, CatalogClientException, TransformerException, IOException { 287 288 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 289 290 // result is a very short hashmap with only one entry! 291 Map map = (HashMap) result; 292 // key = data catalog name; value = csw:GetRecordByIdResponse 293 Iterator it = map.keySet().iterator(); 294 295 String catalog = null; 296 Document doc = null; 297 String docString = null; 298 299 URL u = null; 300 StringBuffer htmlFragment = new StringBuffer( 5000 ); 301 MetadataTransformer mt = null; 302 try { 303 u = new URL( pathToXslFile ); 304 mt = new MetadataTransformer( u.getFile() ); 305 } catch ( MalformedURLException e ) { 306 LOG.logError( e.getMessage(), e ); 307 } catch ( FileNotFoundException e ) { 308 LOG.logError( e.getMessage(), e ); 309 } 310 311 while ( it.hasNext() ) { 312 catalog = (String) it.next(); 313 doc = (Document) map.get( catalog ); 314 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 315 LOG.logDebug( "xml doc to transform:\n", 316 new XMLFragment( doc.getDocumentElement() ).getAsPrettyString() ); 317 } 318 docString = DOMPrinter.nodeToString( doc, CharsetUtils.getSystemCharset() ); 319 Reader reader = new StringReader( docString ); 320 321 List nl = extractMetadata( doc ); 322 if ( nl.size() > 1 ) { 323 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_TOO_MANY_NODES" ) ); 324 } 325 326 String xPathToId = config.getXPathToDataIdentifier(); 327 String identifier = extractValue( (Node) nl.get( 0 ), xPathToId ); 328 String[] serviceCatalogs = null; 329 Map catalogsMap = (HashMap) session.getAttribute( SESSION_AVAILABLESERVICECATALOGS ); 330 if ( catalogsMap != null ) { 331 serviceCatalogs = extractServiceCatalogs( catalogsMap, identifier ); 332 } 333 334 // transformation 335 htmlFragment.append( mt.transformMetadata( reader, catalog, serviceCatalogs, 0, 0, metaVersion ) ); 336 LOG.logDebug( "Transformed html", htmlFragment.toString() ); 337 } 338 339 this.getRequest().setAttribute( HTML_FRAGMENT, htmlFragment.toString() ); 340 session.setAttribute( SESSION_METADATA, result ); 341 } 342 343 /** 344 * Extracts all Metadata nodes from the passed csw:GetRecordByIdResponse Document. 345 * 346 * @param doc 347 * The csw:GetRecordByIdResponse Document from which to extract the Metadata nodes. 348 * @return Returns a NodeList of Metadata Elements for the passed Document. 349 * @throws CatalogClientException 350 * if metadata nodes could not be extracted from the passed Document. 351 * @throws XMLParsingException 352 */ 353 @Override 354 protected List extractMetadata( Document doc ) 355 throws CatalogClientException, XMLParsingException { 356 357 List nl = null; 358 359 String xPathToMetadata = "csw202:GetRecordByIdResponse/child::*"; 360 361 nl = XMLTools.getNodes( doc, xPathToMetadata, nsContext ); 362 363 if ( nl == null || nl.size() < 1 ) { 364 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_EXTRACT_MD_NODES" ) ); 365 } 366 367 return nl; 368 } 369 370 /** 371 * Extracts a List of available service catalogues from the Map in the session and returns its contents as an Array 372 * of Strings. 373 * 374 * @param catalogsMap 375 * The Map containing the data title (as key) and the List of available service catalogues names (as 376 * value) 377 * @param title 378 * The key for the value in the passed Map. 379 * @return Returns an Array of Strings for the available service catalogues. If no service catalogues are available, 380 * an Array of one empty String is returned. 381 */ 382 protected String[] extractServiceCatalogs( Map catalogsMap, String title ) { 383 384 String[] catalogs = null; 385 386 List catalogsList = (ArrayList) catalogsMap.get( title ); 387 388 if ( catalogsList != null ) { 389 catalogs = new String[catalogsList.size()]; 390 for ( int i = 0; i < catalogsList.size(); i++ ) { 391 catalogs[i] = (String) catalogsList.get( i ); 392 } 393 } else { 394 catalogs = new String[] { "" }; 395 } 396 397 return catalogs; 398 } 399 400 }