001 // $HeadURL:
002 // /cvsroot/deegree/src/org/deegree/ogcwebservices/wcs/getcapabilities/WCSRequestValidator.java,v
003 // 1.6 2004/07/12 11:14:19 ap Exp $
004 /*---------------- FILE HEADER ------------------------------------------
005
006 This file is part of deegree.
007 Copyright (C) 2001-2006 by:
008 EXSE, Department of Geography, University of Bonn
009 http://www.giub.uni-bonn.de/deegree/
010 lat/lon GmbH
011 http://www.lat-lon.de
012
013 This library is free software; you can redistribute it and/or
014 modify it under the terms of the GNU Lesser General Public
015 License as published by the Free Software Foundation; either
016 version 2.1 of the License, or (at your option) any later version.
017
018 This library is distributed in the hope that it will be useful,
019 but WITHOUT ANY WARRANTY; without even the implied warranty of
020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
021 Lesser General Public License for more details.
022
023 You should have received a copy of the GNU Lesser General Public
024 License along with this library; if not, write to the Free Software
025 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
026
027 Contact:
028
029 Andreas Poth
030 lat/lon GmbH
031 Aennchenstr. 19
032 53115 Bonn
033 Germany
034 E-Mail: poth@lat-lon.de
035
036 Prof. Dr. Klaus Greve
037 Department of Geography
038 University of Bonn
039 Meckenheimer Allee 166
040 53115 Bonn
041 Germany
042 E-Mail: greve@giub.uni-bonn.de
043
044
045 ---------------------------------------------------------------------------*/
046 package org.deegree.ogcwebservices.wcs.getcapabilities;
047
048 import java.net.URI;
049 import java.net.URL;
050
051 import org.deegree.datatypes.Code;
052 import org.deegree.datatypes.CodeList;
053 import org.deegree.framework.log.ILogger;
054 import org.deegree.framework.log.LoggerFactory;
055 import org.deegree.model.crs.CRSFactory;
056 import org.deegree.model.crs.GeoTransformer;
057 import org.deegree.model.crs.IGeoTransformer;
058 import org.deegree.model.crs.UnknownCRSException;
059 import org.deegree.model.spatialschema.Envelope;
060 import org.deegree.model.spatialschema.GeometryFactory;
061 import org.deegree.ogcbase.ExceptionCode;
062 import org.deegree.ogcwebservices.CurrentUpdateSequenceException;
063 import org.deegree.ogcwebservices.InvalidParameterValueException;
064 import org.deegree.ogcwebservices.InvalidUpdateSequenceException;
065 import org.deegree.ogcwebservices.LonLatEnvelope;
066 import org.deegree.ogcwebservices.OGCWebServiceException;
067 import org.deegree.ogcwebservices.OGCWebServiceRequest;
068 import org.deegree.ogcwebservices.SupportedFormats;
069 import org.deegree.ogcwebservices.wcs.CoverageOfferingBrief;
070 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription;
071 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
072 import org.deegree.ogcwebservices.wcs.describecoverage.DescribeCoverage;
073 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
074
075 /**
076 * @version $Revision: 6259 $
077 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
078 * @author last edited by: $Author: bezema $
079 *
080 * @version 1.0. $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
081 *
082 * @since 2.0
083 */
084 public class WCSRequestValidator {
085
086 private static final ILogger LOG = LoggerFactory.getLogger( WCSRequestValidator.class );
087
088 /**
089 * validates the passed <tt>AbstractOGCWebServiceRequest</tt> which must
090 * be a request that is known by a WCS against the passed
091 * <tt>WCSCapabilities</tt>
092 *
093 * @param capabilities
094 * @param request
095 * @throws CurrentUpdateSequenceException
096 * @throws InvalidUpdateSequenceException
097 * @throws OGCWebServiceException
098 */
099 public static void validate(WCSCapabilities capabilities,
100 OGCWebServiceRequest request)
101 throws CurrentUpdateSequenceException,
102 InvalidUpdateSequenceException, OGCWebServiceException {
103 // schmitz: since we only support one version, we can actually just ignore
104 // the attribute (at least for GetCapabilities requests). I do not think
105 // it does any harm to remove it completely.
106
107 // if ( !request.getVersion().equals(capabilities.getVersion() )) {
108 // throw new InvalidParameterValueException(request.getVersion() + " is not " +
109 // "a valid version for requesting this WCS");
110 // }
111
112 if (request instanceof WCSGetCapabilities) {
113 validate(capabilities, (WCSGetCapabilities) request);
114 } else if (request instanceof GetCoverage) {
115 validate( capabilities, (GetCoverage)request );
116 } else if (request instanceof DescribeCoverage) {
117 validate(capabilities, (DescribeCoverage) request);
118 } else {
119 throw new OGCWebServiceException("Invalid request type: " + request);
120 }
121 }
122
123 /**
124 * validates the passed <tt>WCSGetCapabilities</tt> against the passed
125 * <tt>WCSCapabilities</tt>
126 *
127 * @param capabilities
128 * @param request
129 * @throws CurrentUpdateSequenceException
130 * @throws InvalidUpdateSequenceException
131 */
132 private static void validate(WCSCapabilities capabilities,
133 WCSGetCapabilities request) throws CurrentUpdateSequenceException,
134 InvalidUpdateSequenceException {
135 String rUp = request.getUpdateSequence();
136 String cUp = capabilities.getUpdateSequence();
137
138 if ((rUp != null) && (cUp != null) && (rUp.compareTo(cUp) == 0)) {
139 ExceptionCode code = ExceptionCode.CURRENT_UPDATE_SEQUENCE;
140 throw new CurrentUpdateSequenceException("WCS GetCapabilities",
141 "request update sequence: " + rUp
142 + "is equal to capabilities" + " update sequence "
143 + cUp, code);
144 }
145
146 if ((rUp != null) && (cUp != null) && (rUp.compareTo(cUp) > 0)) {
147 ExceptionCode code = ExceptionCode.INVALID_UPDATESEQUENCE;
148 throw new InvalidUpdateSequenceException("WCS GetCapabilities",
149 "request update sequence: " + rUp + " is higher then the "
150 + "capabilities update sequence " + cUp, code);
151 }
152 }
153
154 /**
155 * validates the passed <tt>DescribeCoverage</tt> against the passed
156 * <tt>WCSCapabilities</tt>
157 *
158 * @param capabilities
159 * @param request
160 * @throws InvalidParameterValueException
161 */
162 private static void validate(WCSCapabilities capabilities,
163 DescribeCoverage request) throws InvalidParameterValueException {
164 String[] coverages = request.getCoverages();
165 if (coverages != null) {
166 ContentMetadata cm = capabilities.getContentMetadata();
167 for (int i = 0; i < coverages.length; i++) {
168 if (cm.getCoverageOfferingBrief(coverages[i]) == null) {
169 throw new InvalidParameterValueException(
170 "Coverage: " + coverages[i] + "is not known by the WCS"); }
171 }
172 }
173 }
174
175 /**
176 * validates the passed <tt>GetCoverage</tt> against the passed
177 * <tt>WCSCapabilities</tt>
178 *
179 * @param capabilities
180 * @param request
181 * @throws InvalidParameterValueException
182 */
183 private static void validate(WCSCapabilities capabilities,
184 GetCoverage request) throws InvalidParameterValueException {
185 String coverage = request.getSourceCoverage();
186 ContentMetadata cm = capabilities.getContentMetadata();
187 // is coverage known by the WCS?
188 CoverageOfferingBrief cob = cm.getCoverageOfferingBrief(coverage);
189 if (cob == null) { throw new InvalidParameterValueException(
190 "Coverage: " + coverage + " is not known by the WCS"); }
191
192 URL url = cob.getConfiguration();
193 CoverageDescription cd = null;
194 try {
195 cd = CoverageDescription.createCoverageDescription(url);
196 } catch (Exception e) {
197 LOG.logError( e.getMessage(), e );
198 throw new InvalidParameterValueException( e.getMessage() );
199 }
200 CoverageOffering co = cd.getCoverageOffering(coverage);
201 if (co == null ) {
202 throw new InvalidParameterValueException("no coverage descrition " +
203 "available for requested coverage: " + coverage);
204 }
205 // validate requested format
206 String format = request.getOutput().getFormat().getCode();
207 SupportedFormats sf = co.getSupportedFormats();
208 CodeList[] codeList = sf.getFormats();
209 if (!validate(codeList, null, format)) {
210 throw new InvalidParameterValueException( "requested format: " + format
211 + " is not known by the WCS for coverage:" + coverage); }
212 // validate requested response CRS
213 String crs = request.getOutput().getCrs().getCode();
214 URI codeSpace = request.getOutput().getCrs().getCodeSpace();
215 String space = null;
216 if ( codeSpace != null ) {
217 space = codeSpace.toString();
218 }
219
220 CodeList[] rrcrs = co.getSupportedCRSs().getRequestResponseSRSs();
221 CodeList[] rescrs = co.getSupportedCRSs().getResponseSRSs();
222 if (!validate(rrcrs, space, crs) && !validate(rescrs, space, crs)) {
223 throw new InvalidParameterValueException(
224 "requested response CRS: " + crs
225 + " is not known by the WCS " + "for coverage:"
226 + coverage); }
227 // validate requested CRS
228 crs = request.getDomainSubset().getRequestSRS().getCode();
229 codeSpace = request.getDomainSubset().getRequestSRS().getCodeSpace();
230 if ( codeSpace != null ) {
231 space = codeSpace.toString();
232 }
233 CodeList[] reqcrs = co.getSupportedCRSs().getRequestSRSs();
234
235 if (!validate(rrcrs, space, crs) && !validate(reqcrs, space, crs)) {
236 throw new InvalidParameterValueException(
237 "requested request CRS: " + crs
238 + " is not known by the WCS for coverage:" + coverage); }
239 // validate requested envelope
240 Envelope envelope = request.getDomainSubset().getSpatialSubset().getEnvelope();
241 LonLatEnvelope llEnv = cob.getLonLatEnvelope();
242
243 try {
244 if ( !intersects(envelope, request.getDomainSubset().getRequestSRS(), llEnv) ) {
245 throw new InvalidParameterValueException(
246 "requested BBOX: doesn't intersect "
247 + " the area of the requested coverage: "
248 + coverage);
249 }
250 } catch ( UnknownCRSException e ) {
251 throw new InvalidParameterValueException( e );
252 }
253
254 }
255
256 /**
257 * @return true if the passed <tt>CodeList</tt> s contains the also passed
258 * codeSpace-value combination. Otherwise false will be returned
259 *
260 * @param codeList
261 * @param codeSpace
262 * @param value
263 */
264 private static boolean validate(CodeList[] codeList, String codeSpace,
265 String value) {
266 for (int i = 0; i < codeList.length; i++) {
267 if (codeList[i].validate(codeSpace, value)) { return true; }
268 }
269 return false;
270 }
271
272 private static boolean intersects(Envelope envelope, Code reqCRS,
273 LonLatEnvelope llEnv) throws UnknownCRSException {
274 Envelope latlonEnv =
275 GeometryFactory.createEnvelope(llEnv.getMin().getX(),
276 llEnv.getMin().getY(),
277 llEnv.getMax().getX(),
278 llEnv.getMax().getY(),
279 CRSFactory.create("EPSG:4326") );
280 try {
281 if ( !"EPSG:4326".equals( reqCRS.getCode() ) ) {
282 IGeoTransformer gt = new GeoTransformer("EPSG:4326");
283 String crs = reqCRS.getCode();
284 envelope = gt.transform(envelope, crs );
285 }
286 } catch (Exception e) {
287 e.printStackTrace();
288 return false;
289 }
290 return envelope.intersects(latlonEnv);
291 }
292
293 }/* ********************************************************************
294 Changes to this class. What the people have been up to:
295 $Log$
296 Revision 1.18 2007/01/24 17:23:47 schmitz
297 Fixed versioning for WCS compliance.
298
299 Revision 1.17 2006/11/27 09:07:52 poth
300 JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
301
302 Revision 1.16 2006/11/23 09:23:43 bezema
303 added a EPSG:4326 to the longlatenvellope
304
305 Revision 1.15 2006/09/27 16:46:41 poth
306 transformation method signature changed
307
308 Revision 1.14 2006/08/07 13:37:59 poth
309 bug fix - checking for intersection between requested box and a coverages envelope
310
311 Revision 1.13 2006/07/28 08:01:27 schmitz
312 Updated the WMS for 1.1.1 compliance.
313 Fixed some documentation.
314
315 Revision 1.12 2006/07/12 14:46:19 poth
316 comment footer added
317
318 ********************************************************************** */