001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/csw/CatalogueService.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.ogcwebservices.csw; 038 039 import java.net.URL; 040 import java.util.HashMap; 041 import java.util.Map; 042 import java.util.Stack; 043 044 import org.deegree.framework.log.ILogger; 045 import org.deegree.framework.log.LoggerFactory; 046 import org.deegree.framework.trigger.TriggerProvider; 047 import org.deegree.i18n.Messages; 048 import org.deegree.ogcwebservices.MissingParameterValueException; 049 import org.deegree.ogcwebservices.OGCWebService; 050 import org.deegree.ogcwebservices.OGCWebServiceException; 051 import org.deegree.ogcwebservices.OGCWebServiceRequest; 052 import org.deegree.ogcwebservices.csw.capabilities.CatalogueGetCapabilities; 053 import org.deegree.ogcwebservices.csw.capabilities.CatalogueOperationsMetadata; 054 import org.deegree.ogcwebservices.csw.configuration.CatalogueConfiguration; 055 import org.deegree.ogcwebservices.csw.configuration.CatalogueConfigurationDocument; 056 import org.deegree.ogcwebservices.csw.discovery.DescribeRecord; 057 import org.deegree.ogcwebservices.csw.discovery.Discovery; 058 import org.deegree.ogcwebservices.csw.discovery.GetDomain; 059 import org.deegree.ogcwebservices.csw.discovery.GetRecordById; 060 import org.deegree.ogcwebservices.csw.discovery.GetRecords; 061 import org.deegree.ogcwebservices.csw.discovery.GetRepositoryItem; 062 import org.deegree.ogcwebservices.csw.manager.Harvest; 063 import org.deegree.ogcwebservices.csw.manager.Manager; 064 import org.deegree.ogcwebservices.csw.manager.Transaction; 065 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 066 import org.deegree.ogcwebservices.wfs.RemoteWFService; 067 import org.deegree.ogcwebservices.wfs.WFService; 068 import org.deegree.ogcwebservices.wfs.WFServiceFactory; 069 import org.deegree.ogcwebservices.wfs.XMLFactory; 070 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 071 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 072 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration; 073 import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument; 074 075 /** 076 * The Catalogue Service class provides the foundation for an OGC catalogue service. The Catalogue Service class 077 * directly includes only the serviceTypeID attribute. In most cases, this attribute will not be directly visible to 078 * catalogue clients. 079 * <p> 080 * The catalog service is an implementation of the OpenGIS Catalogue Service Specification 2.0. 081 * </p> 082 * 083 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a> 084 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a> 085 * 086 * @author last edited by: $Author: apoth $ 087 * 088 * @version $Revision: 27361 $, $Date: 2010-10-18 20:38:36 +0200 (Mo, 18 Okt 2010) $ 089 * @see <a href="http://www.opengis.org/specs/">OGC Specification </a> 090 */ 091 092 public class CatalogueService implements OGCWebService { 093 094 private static final ILogger LOG = LoggerFactory.getLogger( CatalogueService.class ); 095 096 private static final TriggerProvider TP = TriggerProvider.create( CatalogueService.class ); 097 098 private WFService wfsService; 099 100 private CatalogueConfiguration serviceConfiguration; 101 102 private static Map<URL, OGCWebService> wfsMap = new HashMap<URL, OGCWebService>(); 103 104 private static Map<String, Stack<Manager>> managerPool = new HashMap<String, Stack<Manager>>(); 105 106 private static Map<String, Stack<Discovery>> discoveryPool = new HashMap<String, Stack<Discovery>>(); 107 108 private static final String DEFAULT_VERSION = CSWPropertiesAccess.getString( "DEFAULTVERSION" ); 109 110 /** 111 * Creates a new <code>CatalogService</code> instance. 112 * 113 * @param config 114 * 115 * @return new <code>CatalogService</code> instance. 116 * @throws OGCWebServiceException 117 */ 118 public static final CatalogueService create( CatalogueConfiguration config ) 119 throws OGCWebServiceException { 120 // get WFS: local or remote 121 OGCWebService wfsResource = null; 122 try { 123 CatalogueConfigurationDocument document = new CatalogueConfigurationDocument(); 124 document.setSystemId( config.getSystemId() ); 125 126 URL wfsCapabilitiesFileURL = document.resolve( config.getDeegreeParams().getWfsResource().getHref().toString() ); 127 if ( wfsMap.get( wfsCapabilitiesFileURL ) == null ) { 128 if ( wfsCapabilitiesFileURL.getProtocol().equals( "http" ) ) { 129 WFSCapabilitiesDocument capaDoc = new WFSCapabilitiesDocument(); 130 capaDoc.load( wfsCapabilitiesFileURL ); 131 WFSCapabilities capabilities = (WFSCapabilities) capaDoc.parseCapabilities(); 132 LOG.logInfo( "Creating remote WFS with capabilities file " + wfsCapabilitiesFileURL ); 133 wfsResource = new RemoteWFService( capabilities ); 134 } else { 135 WFSConfigurationDocument capaDoc = new WFSConfigurationDocument(); 136 capaDoc.load( wfsCapabilitiesFileURL ); 137 WFSConfiguration conf = capaDoc.getConfiguration(); 138 LOG.logInfo( "CS-W service: Creating local WFS with capabilities file " + wfsCapabilitiesFileURL ); 139 wfsResource = WFServiceFactory.createInstance( conf ); 140 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 141 LOG.logDebug( "CS-W service: The localwfs was has been successfully created, it's capabilties are: " 142 + XMLFactory.export( (WFSCapabilities) wfsResource.getCapabilities() ).getAsPrettyString() ); 143 } 144 } 145 wfsMap.put( wfsCapabilitiesFileURL, wfsResource ); 146 } else { 147 wfsResource = wfsMap.get( wfsCapabilitiesFileURL ); 148 } 149 } catch ( Exception e ) { 150 LOG.logError( "Error creating WFS for CSW", e ); 151 String msg = Messages.get( "CSW_ERROR_CREATING_WFS", e.getMessage() ); 152 throw new OGCWebServiceException( CatalogueService.class.getName(), msg ); 153 } 154 155 // initialize manager and discovery 156 return new CatalogueService( config, (WFService) wfsResource ); 157 } 158 159 /** 160 * 161 * @param config 162 * @param wfsService 163 */ 164 private CatalogueService( CatalogueConfiguration config, WFService wfsService ) { 165 this.serviceConfiguration = config; 166 this.wfsService = wfsService; 167 } 168 169 /** 170 * Returns the OGC-capabilities of the service. 171 * 172 * @return the OGC-capabilities of the service. 173 * @todo analyze incoming request! return only requested sections 174 */ 175 public OGCCapabilities getCapabilities() { 176 return this.serviceConfiguration; 177 } 178 179 /** 180 * Returns the service type (CSW). 181 * 182 * @return the service type (CSW). 183 */ 184 public String getServiceTypeId() { 185 return this.serviceConfiguration.getServiceIdentification().getServiceType().getCode(); 186 } 187 188 /** 189 * @return Version 190 */ 191 public String getVersion() { 192 return this.serviceConfiguration.getVersion(); 193 } 194 195 /** 196 * Method for event based request processing. 197 * 198 * @param request 199 * request object containing the request 200 * @return an Object which may be one of the following 201 * <ul> 202 * <li>DescribeRecordResult</li> 203 * <li>GetRecordResult</li> 204 * <li>GetRecordByIdResult</li> 205 * <li>TransactionResult</li> 206 * <li>EchoRequest</li> 207 * <li>OGCCapabilities</li> 208 * @throws OGCWebServiceException 209 * 210 * @todo validation of requested version against accepted versions 211 * @todo return type 212 */ 213 public Object doService( OGCWebServiceRequest request ) 214 throws OGCWebServiceException { 215 216 request = (OGCWebServiceRequest) TP.doPreTrigger( this, request )[0]; 217 218 Object response = null; 219 220 LOG.logDebug( "Version of request: " + request.getVersion() ); 221 if ( request instanceof DescribeRecord ) { 222 response = this.getDiscovery().describeRecordType( (DescribeRecord) request ); 223 } else if ( request instanceof GetDomain ) { 224 throw new OGCWebServiceException( getClass().getName(), Messages.get( "CSW_GETDOMAIN_NOT_IMPLEMENTED" ) ); 225 // TODO is not implemented 226 // response = this.getDiscovery().getDomain( (GetDomain) request ); 227 } else if ( request instanceof GetRecords ) { 228 response = this.getDiscovery().query( (GetRecords) request ); 229 } else if ( request instanceof GetRecordById ) { 230 response = this.getDiscovery().query( (GetRecordById) request ); 231 } else if ( request instanceof Transaction ) { 232 Manager manager = this.getManager( request.getVersion() ); 233 response = manager.transaction( (Transaction) request ); 234 releaseManager( request.getVersion(), manager ); 235 } else if ( request instanceof Harvest ) { 236 Manager manager = this.getManager( request.getVersion() ); 237 response = manager.harvestRecords( (Harvest) request ); 238 releaseManager( request.getVersion(), manager ); 239 } else if ( request instanceof CatalogueGetCapabilities ) { 240 response = this.getCapabilities(); 241 } else if ( request instanceof GetRepositoryItem ) { 242 response = this.getDiscovery().guery( (GetRepositoryItem) request ); 243 } else { 244 throw new OGCWebServiceException( Messages.get( "CSW_INVALID_REQUEST_TYPE", request.getClass().getName() ) ); 245 } 246 247 return TP.doPostTrigger( this, response )[0]; 248 } 249 250 /** 251 * @return Returns the discovery. 252 * 253 */ 254 public Discovery getDiscovery() { 255 try { 256 return getDiscovery( DEFAULT_VERSION ); 257 } catch ( OGCWebServiceException e ) { 258 LOG.logWarning( e.getMessage(), e ); 259 return new Discovery( wfsService, serviceConfiguration ); 260 } 261 } 262 263 /** 264 * @return Returns the discovery. 265 * @throws OGCWebServiceException 266 * 267 */ 268 public Discovery getDiscovery( String version ) 269 throws OGCWebServiceException { 270 if ( version == null ) { 271 version = DEFAULT_VERSION; 272 LOG.logDebug( "The version requested for the discovery is null, setting to default version: " + version ); 273 } 274 Discovery discovery = null; 275 LOG.logDebug( "Getting manager for version: " + version ); 276 if ( discoveryPool.size() == 0 ) { 277 discovery = instantiateDiscovery( version ); 278 } else { 279 if ( discoveryPool.containsKey( version ) && discoveryPool.get( version ) != null ) { 280 Stack<Discovery> stack = discoveryPool.get( version ); 281 if ( stack.size() > 0 ) { 282 discovery = stack.pop(); 283 } 284 } else { 285 discoveryPool.put( version, new Stack<Discovery>() ); 286 } 287 if ( discovery == null ) { 288 discovery = instantiateDiscovery( version ); 289 } 290 } 291 return discovery; 292 } 293 294 /** 295 * This method can be used to release the manager back into the pool of managers. If either version or manager is 296 * <code>null</code> this method returns. 297 * 298 * @param version 299 * this manager is created for 300 * @param manager 301 * to be released. 302 */ 303 public synchronized void releaseManager( String version, Manager manager ) { 304 if ( manager == null ) { 305 return; 306 } 307 if ( version == null || "".equals( version ) ) { 308 version = DEFAULT_VERSION; 309 LOG.logDebug( "The version for releasing the manager is null, setting to default version: " + version ); 310 } 311 Stack<Manager> stack = null; 312 if ( managerPool.containsKey( version ) && managerPool.get( version ) != null ) { 313 stack = managerPool.get( version ); 314 } else { 315 stack = new Stack<Manager>(); 316 } 317 stack.push( manager ); 318 managerPool.put( version, stack ); 319 } 320 321 /** 322 * @param version 323 * to get a manager for. 324 * @return the manager. 325 * @throws OGCWebServiceException 326 */ 327 public synchronized Manager getManager( String version ) 328 throws OGCWebServiceException { 329 if ( version == null ) { 330 version = DEFAULT_VERSION; 331 LOG.logDebug( "The version requested for the manager is null, setting to default version: " + version ); 332 } 333 Manager manager = null; 334 LOG.logDebug( "Getting manager for version: " + version ); 335 if ( managerPool.size() == 0 ) { 336 manager = instantiateManager( version ); 337 } else { 338 if ( managerPool.containsKey( version ) && managerPool.get( version ) != null ) { 339 Stack<Manager> stack = managerPool.get( version ); 340 if ( stack.size() > 0 ) { 341 manager = stack.pop(); 342 } 343 } else { 344 managerPool.put( version, new Stack<Manager>() ); 345 } 346 if ( manager == null ) { 347 manager = instantiateManager( version ); 348 } 349 } 350 return manager; 351 } 352 353 private synchronized Manager instantiateManager( String version ) 354 throws OGCWebServiceException { 355 CatalogueOperationsMetadata com = (CatalogueOperationsMetadata) serviceConfiguration.getOperationsMetadata(); 356 Manager manager = null; 357 if ( com.getHarvest() != null || com.getTransaction() != null ) { 358 try { 359 String className = CSWPropertiesAccess.getString( "Manager" + version ); 360 if ( className == null ) { 361 String msg = Messages.get( "CSW_UNSUPPORTED_VERSION", version ); 362 throw new OGCWebServiceException( getClass().getName(), msg ); 363 } 364 LOG.logDebug( "Manager class used: " + className ); 365 manager = (Manager) Class.forName( className ).newInstance(); 366 manager.init( wfsService, serviceConfiguration ); 367 } catch ( MissingParameterValueException e ) { 368 LOG.logError( e.getMessage(), e ); 369 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 370 } catch ( InstantiationException e ) { 371 LOG.logError( e.getMessage(), e ); 372 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 373 } catch ( IllegalAccessException e ) { 374 LOG.logError( e.getMessage(), e ); 375 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 376 } catch ( ClassNotFoundException e ) { 377 LOG.logError( e.getMessage(), e ); 378 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 379 } 380 } else { 381 throw new OGCWebServiceException( getClass().getName(), Messages.get( "CSW_TRANSCATIONS_ARE_NOT_DEFINED" ) ); 382 } 383 return manager; 384 } 385 386 private synchronized Discovery instantiateDiscovery( String version ) 387 throws OGCWebServiceException { 388 CatalogueOperationsMetadata com = (CatalogueOperationsMetadata) serviceConfiguration.getOperationsMetadata(); 389 Discovery discovery = null; 390 if ( com.getHarvest() != null || com.getTransaction() != null ) { 391 try { 392 String className = CSWPropertiesAccess.getString( "Discovery" + version ); 393 if ( className == null ) { 394 String msg = Messages.get( "CSW_UNSUPPORTED_VERSION", version ); 395 throw new OGCWebServiceException( getClass().getName(), msg ); 396 } 397 LOG.logDebug( "Discovery class used: " + className ); 398 discovery = (Discovery) Class.forName( className ).newInstance(); 399 discovery.init( wfsService, serviceConfiguration ); 400 } catch ( MissingParameterValueException e ) { 401 LOG.logError( e.getMessage(), e ); 402 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 403 } catch ( InstantiationException e ) { 404 LOG.logError( e.getMessage(), e ); 405 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 406 } catch ( IllegalAccessException e ) { 407 LOG.logError( e.getMessage(), e ); 408 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 409 } catch ( ClassNotFoundException e ) { 410 LOG.logError( e.getMessage(), e ); 411 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 412 } 413 } else { 414 throw new OGCWebServiceException( getClass().getName(), Messages.get( "CSW_TRANSCATIONS_ARE_NOT_DEFINED" ) ); 415 } 416 return discovery; 417 } 418 419 }