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 ********************************************************************** */