001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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: mschneider $ 087 * 088 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 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 Discovery discovery; 099 100 private WFService wfsService; 101 102 private CatalogueConfiguration serviceConfiguration; 103 104 private static Map<URL, OGCWebService> wfsMap = new HashMap<URL, OGCWebService>(); 105 106 private static Map<String, Stack<Manager>> managerPool = new HashMap<String, Stack<Manager>>(); 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 this.discovery = new Discovery( wfsService, config ); 168 } 169 170 /** 171 * Returns the OGC-capabilities of the service. 172 * 173 * @return the OGC-capabilities of the service. 174 * @todo analyze incoming request! return only requested sections 175 */ 176 public OGCCapabilities getCapabilities() { 177 return this.serviceConfiguration; 178 } 179 180 /** 181 * Returns the service type (CSW). 182 * 183 * @return the service type (CSW). 184 */ 185 public String getServiceTypeId() { 186 return this.serviceConfiguration.getServiceIdentification().getServiceType().getCode(); 187 } 188 189 /** 190 * @return Version 191 */ 192 public String getVersion() { 193 return this.serviceConfiguration.getVersion(); 194 } 195 196 /** 197 * Method for event based request processing. 198 * 199 * @param request 200 * request object containing the request 201 * @return an Object which may be one of the following 202 * <ul> 203 * <li>DescribeRecordResult</li> 204 * <li>GetRecordResult</li> 205 * <li>GetRecordByIdResult</li> 206 * <li>TransactionResult</li> 207 * <li>EchoRequest</li> 208 * <li>OGCCapabilities</li> 209 * @throws OGCWebServiceException 210 * 211 * @todo validation of requested version against accepted versions 212 * @todo return type 213 */ 214 public Object doService( OGCWebServiceRequest request ) 215 throws OGCWebServiceException { 216 217 request = (OGCWebServiceRequest) TP.doPreTrigger( this, request )[0]; 218 219 Object response = null; 220 221 LOG.logDebug( "Version of request: " + request.getVersion() ); 222 if ( request instanceof DescribeRecord ) { 223 response = this.getDiscovery().describeRecordType( (DescribeRecord) request ); 224 } else if ( request instanceof GetDomain ) { 225 throw new OGCWebServiceException( getClass().getName(), Messages.get( "CSW_GETDOMAIN_NOT_IMPLEMENTED" ) ); 226 // TODO is not implemented 227 // response = this.getDiscovery().getDomain( (GetDomain) request ); 228 } else if ( request instanceof GetRecords ) { 229 response = this.getDiscovery().query( (GetRecords) request ); 230 } else if ( request instanceof GetRecordById ) { 231 response = this.getDiscovery().query( (GetRecordById) request ); 232 } else if ( request instanceof Transaction ) { 233 Manager manager = this.getManager( request.getVersion() ); 234 response = manager.transaction( (Transaction) request ); 235 releaseManager( request.getVersion(), manager ); 236 } else if ( request instanceof Harvest ) { 237 Manager manager = this.getManager( request.getVersion() ); 238 response = manager.harvestRecords( (Harvest) request ); 239 releaseManager( request.getVersion(), manager ); 240 } else if ( request instanceof CatalogueGetCapabilities ) { 241 response = this.getCapabilities(); 242 } else if ( request instanceof GetRepositoryItem ) { 243 response = this.getDiscovery().guery( (GetRepositoryItem) request ); 244 } else { 245 throw new OGCWebServiceException( Messages.get( "CSW_INVALID_REQUEST_TYPE", request.getClass().getName() ) ); 246 } 247 248 return TP.doPostTrigger( this, response )[0]; 249 } 250 251 /** 252 * @return Returns the discovery. 253 * 254 */ 255 public Discovery getDiscovery() { 256 return discovery; 257 } 258 259 /** 260 * This method can be used to release the manager back into the pool of managers. If either version or manager is 261 * <code>null</code> this method returns. 262 * 263 * @param version 264 * this manager is created for 265 * @param manager 266 * to be released. 267 */ 268 public synchronized void releaseManager( String version, Manager manager ) { 269 if ( manager == null ) { 270 return; 271 } 272 if ( version == null || "".equals( version ) ) { 273 version = DEFAULT_VERSION; 274 LOG.logDebug( "The version for releasing the manager is null, setting to default version: " + version ); 275 } 276 Stack<Manager> stack = null; 277 if ( managerPool.containsKey( version ) && managerPool.get( version ) != null ) { 278 stack = managerPool.get( version ); 279 } else { 280 stack = new Stack<Manager>(); 281 } 282 stack.push( manager ); 283 managerPool.put( version, stack ); 284 } 285 286 /** 287 * @param version 288 * to get a manager for. 289 * @return the manager. 290 * @throws OGCWebServiceException 291 */ 292 public synchronized Manager getManager( String version ) 293 throws OGCWebServiceException { 294 if ( version == null ) { 295 version = DEFAULT_VERSION; 296 LOG.logDebug( "The version requested for the manager is null, setting to default version: " + version ); 297 } 298 Manager manager = null; 299 LOG.logDebug( "Getting manager for version: " + version ); 300 if ( managerPool.size() == 0 ) { 301 manager = instantiateManager( version ); 302 } else { 303 if ( managerPool.containsKey( version ) && managerPool.get( version ) != null ) { 304 Stack<Manager> stack = managerPool.get( version ); 305 if ( stack.size() > 0 ) { 306 manager = stack.pop(); 307 } 308 } else { 309 managerPool.put( version, new Stack<Manager>() ); 310 } 311 if ( manager == null ) { 312 manager = instantiateManager( version ); 313 } 314 } 315 return manager; 316 } 317 318 private synchronized Manager instantiateManager( String version ) 319 throws OGCWebServiceException { 320 CatalogueOperationsMetadata com = (CatalogueOperationsMetadata) serviceConfiguration.getOperationsMetadata(); 321 Manager manager = null; 322 if ( com.getHarvest() != null || com.getTransaction() != null ) { 323 try { 324 String className = CSWPropertiesAccess.getString( "Manager" + version ); 325 if ( className == null ) { 326 String msg = Messages.get( "CSW_UNSUPPORTED_VERSION", version ); 327 throw new OGCWebServiceException( getClass().getName(), msg ); 328 } 329 LOG.logDebug( "Manager class used: " + className ); 330 manager = (Manager) Class.forName( className ).newInstance(); 331 manager.init( wfsService, serviceConfiguration ); 332 } catch ( MissingParameterValueException e ) { 333 LOG.logError( e.getMessage(), e ); 334 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 335 } catch ( InstantiationException e ) { 336 LOG.logError( e.getMessage(), e ); 337 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 338 } catch ( IllegalAccessException e ) { 339 LOG.logError( e.getMessage(), e ); 340 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 341 } catch ( ClassNotFoundException e ) { 342 LOG.logError( e.getMessage(), e ); 343 throw new OGCWebServiceException( getClass().getName(), e.getMessage() ); 344 } 345 } else { 346 throw new OGCWebServiceException( getClass().getName(), Messages.get( "CSW_TRANSCATIONS_ARE_NOT_DEFINED" ) ); 347 } 348 return manager; 349 } 350 351 }