001 //$Header: /deegreerepository/deegree/src/org/deegree/ogcwebservices/wfs/WFService.java,v 1.46 2007/03/14 14:43:44 mschneider Exp $
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 package org.deegree.ogcwebservices.wfs;
037
038 import static java.util.Arrays.asList;
039 import static java.util.Collections.disjoint;
040 import static org.deegree.i18n.Messages.get;
041 import static org.deegree.ogcbase.ExceptionCode.INVALID_UPDATESEQUENCE;
042 import static org.deegree.ogcbase.ExceptionCode.VERSIONNEGOTIATIONFAILED;
043
044 import java.util.List;
045 import java.util.Map;
046
047 import org.deegree.datatypes.QualifiedName;
048 import org.deegree.framework.log.ILogger;
049 import org.deegree.framework.log.LoggerFactory;
050 import org.deegree.framework.trigger.TriggerProvider;
051 import org.deegree.io.datastore.LockManager;
052 import org.deegree.io.datastore.schema.MappedFeatureType;
053 import org.deegree.ogcwebservices.OGCWebService;
054 import org.deegree.ogcwebservices.OGCWebServiceException;
055 import org.deegree.ogcwebservices.OGCWebServiceRequest;
056 import org.deegree.ogcwebservices.getcapabilities.Operation;
057 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
058 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration;
059 import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType;
060 import org.deegree.ogcwebservices.wfs.operation.GetFeature;
061 import org.deegree.ogcwebservices.wfs.operation.GetFeatureWithLock;
062 import org.deegree.ogcwebservices.wfs.operation.GetGmlObject;
063 import org.deegree.ogcwebservices.wfs.operation.LockFeature;
064 import org.deegree.ogcwebservices.wfs.operation.WFSGetCapabilities;
065 import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction;
066 import org.deegree.owscommon.OWSDomainType;
067
068 /**
069 * This class implements access to the methods defined in the OGC WFS 1.1.0 specification.
070 *
071 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
072 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
073 * @author last edited by: $Author: aionita $
074 *
075 * @version $Revision: 23794 $, $Date: 2010-04-23 15:05:33 +0200 (Fr, 23 Apr 2010) $
076 *
077 * @see OGCWebService
078 */
079 public class WFService implements OGCWebService {
080
081 private static final ILogger LOG = LoggerFactory.getLogger( WFService.class );
082
083 /** Only OGC standard version currently implemented by this service. */
084 public static final String VERSION = "1.1.0";
085
086 private static final TriggerProvider TP = TriggerProvider.create( WFService.class );
087
088 private WFSConfiguration configuration;
089
090 // shared instance that handles all GetFeature requests to this service
091 private GetFeatureHandler getFeatureHandler;
092
093 // shared instance that handles all DescribeFeatureType requests to this service
094 private DescribeFeatureTypeHandler describeFTHandler;
095
096 // shared instance that handles all LockFeature requests to this service
097 private LockFeatureHandler lockFeatureHandler;
098
099 private GetGmlObjectHandler getGmlObjectHandler;
100
101 /**
102 * Creates a new instance of <code>WFService</code> with the given configuration.
103 *
104 * @param configuration
105 * @throws OGCWebServiceException
106 */
107 WFService( WFSConfiguration configuration ) throws OGCWebServiceException {
108 this.configuration = configuration;
109 this.getFeatureHandler = new GetFeatureHandler( this );
110 this.describeFTHandler = new DescribeFeatureTypeHandler( this );
111 this.lockFeatureHandler = new LockFeatureHandler( this );
112 getGmlObjectHandler = new GetGmlObjectHandler( configuration );
113 }
114
115 /**
116 * Returns the capabilities of the <code>WFService</code>.
117 *
118 * @return the capabilities, this is actually a <code>WFSConfiguration</code> instance
119 */
120 public WFSCapabilities getCapabilities() {
121 return this.configuration;
122 }
123
124 /**
125 * Performs the handling of the passed OGCWebServiceEvent directly and returns the result to the calling class/
126 * method.
127 *
128 * @param request
129 * WFS request to perform
130 *
131 * @throws OGCWebServiceException
132 */
133 public Object doService( OGCWebServiceRequest request )
134 throws OGCWebServiceException {
135
136 long ts = System.currentTimeMillis();
137 request = (OGCWebServiceRequest) TP.doPreTrigger( this, request )[0];
138
139 Object response = null;
140 if ( request instanceof WFSGetCapabilities ) {
141 validateGetCapabilitiesRequest( (WFSGetCapabilities) request );
142 response = this.configuration;
143 } else if ( request instanceof GetFeatureWithLock ) {
144 response = this.lockFeatureHandler.handleRequest( (GetFeatureWithLock) request );
145 } else if ( request instanceof GetFeature ) {
146 ( (GetFeature) request ).guessAllMissingNamespaces( this );
147 response = this.getFeatureHandler.handleRequest( (GetFeature) request );
148 } else if ( request instanceof DescribeFeatureType ) {
149 ( (DescribeFeatureType) request ).guessMissingNamespaces( this );
150 response = this.describeFTHandler.handleRequest( (DescribeFeatureType) request );
151 } else if ( request instanceof Transaction ) {
152 ( (Transaction) request ).guessMissingNamespaces( this );
153 TransactionHandler handler = new TransactionHandler( this, (Transaction) request );
154 response = handler.handleRequest();
155 } else if ( request instanceof LockFeature ) {
156 ( (LockFeature) request ).guessMissingNamespaces( this );
157 response = this.lockFeatureHandler.handleRequest( (LockFeature) request );
158 } else if ( request instanceof GetGmlObject ) {
159 response = getGmlObjectHandler.handleRequest( (GetGmlObject) request );
160 } else {
161 String msg = "Unknown request type: " + request.getClass().getName();
162 throw new OGCWebServiceException( getClass().getName(), msg );
163 }
164
165 Object o = TP.doPostTrigger( this, response )[0];
166 if ( LOG.isDebug() ) {
167 LOG.logDebug( "Using lockmanager instance: " + LockManager.getInstance() );
168 LOG.logDebug( "WFS processing time for request type " + request.getClass().getSimpleName() + ": ",
169 Long.toString( ( System.currentTimeMillis() - ts ) ) );
170 }
171 return o;
172 }
173
174 // throws exception if it's required by the spec
175 private void validateGetCapabilitiesRequest( WFSGetCapabilities request )
176 throws OGCWebServiceException {
177 // version negotiation
178 if ( request.getAcceptVersions() != null && request.getAcceptVersions().length != 0 ) {
179 Operation op = configuration.getOperationsMetadata().getGetCapabilitiesOperation();
180 OWSDomainType versions = op.getParameter( "AcceptVersions" );
181 List<String> vs1 = asList( versions.getValues() );
182 List<String> vs2 = asList( request.getAcceptVersions() );
183
184 if ( disjoint( vs1, vs2 ) ) {
185 throw new OGCWebServiceException( get( "WFS_VERSION_NEGOTIATION_FAILED" ), VERSIONNEGOTIATIONFAILED );
186 }
187 }
188
189 if ( request.getUpdateSequence() != null ) {
190 // check update sequences
191 String seq = configuration.getUpdateSequence();
192 if ( !request.getUpdateSequence().equals( "" ) && seq.compareTo( request.getUpdateSequence() ) < 0 ) {
193 throw new OGCWebServiceException( "updatesequence", get( "UPDATESEQUENCE_INVALID" ),
194 INVALID_UPDATESEQUENCE );
195 }
196 }
197 }
198
199 /**
200 * Returns a clone of the <code>WFService</code> instance.
201 * <p>
202 * Note that the configuration of the new service will refer to the same instance.
203 */
204 @Override
205 public Object clone() {
206
207 WFService clone = null;
208 try {
209 clone = new WFService( configuration );
210 } catch ( OGCWebServiceException e ) {
211 // can never happen
212 }
213 return clone;
214 }
215
216 /**
217 * Returns the <code>MappedFeatureType</code> with the given name.
218 *
219 * @param name
220 * name of the feature type
221 * @return the mapped feature type with the given name, or null if it is not known to this WFService instance
222 */
223 public MappedFeatureType getMappedFeatureType( QualifiedName name ) {
224 return this.configuration.getMappedFeatureTypes().get( name );
225 }
226
227 /**
228 * Returns a <code>Map</code> of the feature types that this WFS serves.
229 *
230 * @return keys: feature type names, values: mapped feature types
231 */
232 public Map<QualifiedName, MappedFeatureType> getMappedFeatureTypes() {
233 return this.configuration.getMappedFeatureTypes();
234 }
235 }