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 }