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 }