001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wps/execute/ExecuteRequestHandler.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/exse/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstraße 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.ogcwebservices.wps.execute; 044 045 import java.util.HashMap; 046 import java.util.List; 047 import java.util.Map; 048 049 import org.deegree.datatypes.Code; 050 import org.deegree.datatypes.values.TypedLiteral; 051 import org.deegree.framework.log.ILogger; 052 import org.deegree.framework.log.LoggerFactory; 053 import org.deegree.model.spatialschema.Envelope; 054 import org.deegree.ogcwebservices.InvalidParameterValueException; 055 import org.deegree.ogcwebservices.MissingParameterValueException; 056 import org.deegree.ogcwebservices.OGCWebServiceException; 057 import org.deegree.ogcwebservices.wps.ServerBusyException; 058 import org.deegree.ogcwebservices.wps.WPService; 059 import org.deegree.ogcwebservices.wps.configuration.WPSConfiguration; 060 import org.deegree.ogcwebservices.wps.describeprocess.ComplexData; 061 import org.deegree.ogcwebservices.wps.describeprocess.InputDescription; 062 import org.deegree.ogcwebservices.wps.describeprocess.OutputDescription; 063 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription; 064 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.DataInputs; 065 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.ProcessOutputs; 066 import org.deegree.ogcwebservices.wps.execute.IOValue.ComplexValueReference; 067 068 /** 069 * WPSExecuteRequestHandler.java 070 * 071 * Created on 10.03.2006. 12:11:28h 072 * 073 * @author <a href="mailto:christian@kiehle.org">Christian Kiehle</a> 074 * @author <a href="mailto:christian.heier@gmx.de">Christian Heier</a> 075 * @author last edited by: $Author: apoth $ 076 * 077 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 078 */ 079 public class ExecuteRequestHandler { 080 081 private static final ILogger LOG = LoggerFactory.getLogger( ExecuteRequestHandler.class ); 082 083 private WPService wpService = null; 084 085 private static WPSConfiguration wpsConfiguration = null; 086 087 /** 088 * 089 * @param wpService 090 */ 091 public ExecuteRequestHandler( WPService wpService ) { 092 this.wpService = wpService; 093 // Get configuration from current wps instance 094 wpsConfiguration = this.wpService.getConfiguration(); 095 } 096 097 /** 098 * 099 * @param executeRequest 100 * @return 101 * @throws OGCWebServiceException 102 */ 103 public ExecuteResponse handleRequest( ExecuteRequest executeRequest ) 104 throws OGCWebServiceException { 105 106 // Get the map of registered Processes from wps configuration 107 Map<String, Process> registeredProcessesMap = wpsConfiguration.getRegisteredProcesses(); 108 109 // Get the identifier of the process to be executed from the 110 // ExecuteRequest 111 Code executeProcessIdentifier = executeRequest.getIdentifier(); 112 113 // Get the requested process from the registered processes 114 Process process = registeredProcessesMap.get( executeProcessIdentifier.getCode().toUpperCase() ); 115 116 if ( null == process ) { 117 118 // Unknown process was requested 119 String msg = "A process with identifier '" + executeRequest.getIdentifier().getCode() 120 + "' is not known to this wpserver."; 121 LOG.logDebug( msg ); 122 throw new InvalidParameterValueException( getClass().getName(), msg ); 123 } 124 125 // Get request queue manager from configuration 126 RequestQueueManager requestQueueManager = wpsConfiguration.getDeegreeParams().getRequestQueueManager(); 127 128 // add current request to queue 129 boolean success = requestQueueManager.addRequestToQueue( executeRequest ); 130 131 Status status = null; 132 133 if ( success ) { 134 status = new Status(); 135 String msg = "Your execute request has been successfully added to the RequestQueue. The current length of the RequestQueue is " 136 + requestQueueManager.getLengthOfQueue(); 137 LOG.logDebug( msg ); 138 status.setProcessAccepted( msg ); 139 } else { 140 String msg = "The server is too busy to accept and queue the request at this time."; 141 LOG.logError( msg ); 142 throw new ServerBusyException( msg ); 143 } 144 145 // TODO implement multiple threads handling 146 if ( 0 < requestQueueManager.getLengthOfQueue() ) { 147 executeRequest = requestQueueManager.getRequestFromQueue(); 148 } 149 150 // Instantiate new execute response 151 // this response will be populated during the following workflow 152 ExecuteResponse executeResponse = new ExecuteResponse(); 153 154 // Set identifier in response according to requested process 155 executeResponse.setIdentifier( process.getProcessDescription().getIdentifier() ); 156 157 // Add current status to response 158 executeResponse.setStatus( status ); 159 160 // Set version in response according to configuration 161 executeResponse.setVersion( wpsConfiguration.getVersion() ); 162 163 // Copy inputs from request to response 164 ExecuteDataInputs executeDataInputs = executeRequest.getDataInputs(); 165 if ( null != executeDataInputs ) { 166 executeResponse.setDataInputs( executeDataInputs ); 167 } 168 169 // Copy outputdefinitions from request to response 170 OutputDefinitions outputDefinitions = executeRequest.getOutputDefinitions(); 171 if ( null != outputDefinitions ) { 172 executeResponse.setOutputDefinitions( outputDefinitions ); 173 } 174 175 handleStoreParameter( process, executeRequest, executeResponse ); 176 177 return executeResponse; 178 } 179 180 /** 181 * 182 * @param process 183 * @param executeRequest 184 * @param executeResponse 185 * @throws OGCWebServiceException 186 */ 187 private static void handleStoreParameter( Process process, ExecuteRequest executeRequest, 188 ExecuteResponse executeResponse ) 189 throws OGCWebServiceException { 190 191 boolean store = executeRequest.isStore(); 192 193 if ( store ) { 194 195 // TODO store (optional) currently not supported 196 // @see OGC 05-007r4 Table 27 197 // @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2 198 throw new InvalidParameterValueException( "store", 199 "Store is not supported by this WPServer instance." ); 200 // handleStatusParameter(process, executeRequest, executeResponse); 201 202 } 203 204 // Get configured process outputs 205 ProcessOutputs configuredProcessOutputs = process.getProcessDescription().getProcessOutputs(); 206 207 // Get list of outputdescriptions from configured process outputs 208 List<OutputDescription> outputDescriptionsList = configuredProcessOutputs.getOutput(); 209 210 /* 211 * @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2 212 * @see OGC 05-007r4 Table 27: If the store parameter is false, there is only one output, 213 * and that output has a ComplexValue, then this ComplexValue shall be returned to the 214 * client outside of any ExecuteResponse document. 215 * 216 */ 217 if ( 1 == outputDescriptionsList.size() ) { 218 OutputDescription outputDescription = outputDescriptionsList.get( 0 ); 219 220 ComplexData complexOutput = outputDescription.getComplexOutput(); 221 222 if ( null != complexOutput ) { 223 executeResponse.setDirectResponse( true ); 224 startProcess( process, executeRequest, executeResponse ); 225 } else { 226 handleStatusParameter( process, executeRequest, executeResponse ); 227 } 228 } else { 229 handleStatusParameter( process, executeRequest, executeResponse ); 230 } 231 232 } 233 234 /** 235 * 236 * @param process 237 * @param executeRequest 238 * @param executeResponse 239 * @throws OGCWebServiceException 240 */ 241 private static void handleStatusParameter( Process process, ExecuteRequest executeRequest, 242 ExecuteResponse executeResponse ) 243 throws OGCWebServiceException { 244 245 boolean status = executeRequest.isStatus(); 246 247 if ( status ) { 248 249 // TODO status currently not supported (optional) 250 // @see OGC 05-007r4 Table 27 251 // @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2 252 253 throw new InvalidParameterValueException( "status", 254 "Status is not supported by this WPServer instance." ); 255 256 // save passed response at web accessible location, get full path 257 // and add it as statuslocation to response 258 // saveExecuteResponse(); 259 // executeResponse.setStatusLocation(fullpath); 260 261 // return response to client 262 263 // startProcess(process, executeRequest, executeResponse); 264 265 // update status to process started 266 267 // updateSavedExecuteResponse(); 268 269 } 270 startProcess( process, executeRequest, executeResponse ); 271 272 } 273 274 /** 275 * 276 * @param process 277 * @param executeRequest 278 * @param executeResponse 279 * @throws OGCWebServiceException 280 */ 281 private static void startProcess( Process process, ExecuteRequest executeRequest, 282 ExecuteResponse executeResponse ) 283 throws OGCWebServiceException { 284 285 // Extract map of provided inputs from request 286 Map<String, IOValue> inputs = extractProcessInputs( process.getProcessDescription(), 287 executeRequest ); 288 289 // Extract outputDefinitions from request 290 OutputDefinitions outputDefinitions = executeRequest.getOutputDefinitions(); 291 292 ExecuteResponse.ProcessOutputs processOutputs = process.execute( inputs, outputDefinitions ); 293 294 if ( null != processOutputs ) { 295 296 // Update status in response to successfull 297 Status status = executeResponse.getStatus(); 298 status.setProcessSucceeded( "The " 299 + process.getProcessDescription().getIdentifier().getCode() 300 + " process has been successfully completed" ); 301 executeResponse.setStatus( status ); 302 303 // Add processOutputs to response 304 executeResponse.setProcessOutputs( processOutputs ); 305 } 306 } 307 308 /** 309 * Extract required process inputs from <code>ExecuteRequest</code> 310 * 311 * @param executeRequest 312 * @return processInputs 313 * @throws MissingParameterValueException 314 * @throws InvalidParameterValueException 315 */ 316 private static Map<String, IOValue> extractProcessInputs( 317 ProcessDescription processDescription, 318 ExecuteRequest executeRequest ) 319 throws MissingParameterValueException, InvalidParameterValueException { 320 321 // TODO if complexvaluereferences are included --> load data via a new 322 // threaded method 323 324 // Get inputs provided in executerequest 325 ExecuteDataInputs executeDataInputs = executeRequest.getDataInputs(); 326 Map<String, IOValue> providedInputs = executeDataInputs.getInputs(); 327 328 // Prepare result map 329 Map<String, IOValue> processInputs = null; 330 331 // Get required process inputs from processDescription 332 DataInputs configuredDataInputs = processDescription.getDataInputs(); 333 List<InputDescription> inputDescriptions = configuredDataInputs.getInputDescriptions(); 334 335 // Get inputDescription for each configured input 336 int size = inputDescriptions.size(); 337 338 if ( 0 < size ) { 339 processInputs = new HashMap<String, IOValue>( size ); 340 341 for ( int i = 0; i < size; i++ ) { 342 343 InputDescription inputDescription = inputDescriptions.get( i ); 344 String identifier = inputDescription.getIdentifier().getCode(); 345 int minOccurs = inputDescription.getMinimumOccurs(); 346 347 IOValue ioValue = providedInputs.get( identifier ); 348 349 if ( null == ioValue && 1 == minOccurs ) { 350 throw new MissingParameterValueException( identifier, 351 "A required process input is missing" ); 352 } 353 354 if ( inputDescription.isBoundingBoxData() ) { 355 Envelope boundingBoxValue = ioValue.getBoundingBoxValue(); 356 if ( null == boundingBoxValue ) { 357 throw new InvalidParameterValueException( identifier, 358 "The type of the provided process input is wrong" ); 359 } 360 361 } else if ( inputDescription.isLiteralData() ) { 362 TypedLiteral literalValue = ioValue.getLiteralValue(); 363 if ( null == literalValue ) { 364 throw new InvalidParameterValueException( identifier, 365 "The type of the provided process input is wrong" ); 366 } 367 368 } else if ( inputDescription.isComplexData() ) { 369 ComplexValue complexValue = ioValue.getComplexValue(); 370 ComplexValueReference complexValuereference = ioValue.getComplexValueReference(); 371 if ( null == complexValue && null == complexValuereference ) { 372 throw new InvalidParameterValueException( identifier, 373 "The type of the provided process input is wrong" ); 374 } 375 } 376 377 // TODO load complexvaluereference, add as IOValue to 378 // ProcessInputsmap 379 380 LOG.logDebug( "Found required process input '" + identifier 381 + "' in execute request." ); 382 383 processInputs.put( identifier, ioValue ); 384 } 385 } 386 387 return processInputs; 388 } 389 390 }