package uws.config; /* * This file is part of UWSLibrary. * * UWSLibrary is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * UWSLibrary is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2016 - Astronomisches Rechen Institut (ARI) */ import static uws.config.UWSConfiguration.KEY_REGEXP_MAX_DESTRUCTION_INTERVAL; import static uws.config.UWSConfiguration.KEY_REQUEST_PARSER; import static uws.config.UWSConfiguration.REGEXP_DEFAULT_DESTRUCTION_INTERVAL; import static uws.config.UWSConfiguration.REGEXP_DEFAULT_EXEC_DURATION; import static uws.config.UWSConfiguration.REGEXP_JOB_THREAD; import static uws.config.UWSConfiguration.REGEXP_MAX_EXEC_DURATION; import static uws.config.UWSConfiguration.REGEXP_PARAMETERS; import static uws.config.UWSConfiguration.extractJobListName; import static uws.config.UWSConfiguration.fetchConstructor; import static uws.config.UWSConfiguration.getProperty; import static uws.config.UWSConfiguration.newInstance; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.text.ParseException; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import uws.UWSException; import uws.job.ErrorSummary; import uws.job.JobThread; import uws.job.Result; import uws.job.UWSJob; import uws.job.parameters.DestructionTimeController; import uws.job.parameters.DurationParamController; import uws.job.parameters.ExecutionDurationController; import uws.job.parameters.InputParamController; import uws.job.parameters.NumericParamController; import uws.job.parameters.StringParamController; import uws.job.parameters.UWSParameters; import uws.job.user.JobOwner; import uws.service.UWS; import uws.service.UWSFactory; import uws.service.UWSUrl; import uws.service.file.UWSFileManager; import uws.service.request.RequestParser; import uws.service.request.UWSRequestParser; /** * Concrete implementation of a {@link UWSFactory} which is parameterized by a UWS configuration file. * * @author Grégory Mantelet (ARI) * @version 4.2 (09/2016) * @since 4.2 */ public class ConfigurableUWSFactory implements UWSFactory { /** Constructor of the {@link RequestParser} to create for the whole UWS service. * <p><i>If <code>null</code>, the default UWS request parser (i.e. {@link UWSRequestParser}) will be used.</i></p> */ protected Constructor<? extends RequestParser> constructorRequestParser = null; /** Map associating the name of a job list with the constructor of the class of the jobs to create inside this job list. */ protected Map<String,Constructor<? extends JobThread>> jobThreads = new HashMap<String,Constructor<? extends JobThread>>(2); /** List of parameters (and eventually how to control them) for each job-list/job. */ protected Map<String,Map<String,InputParamController>> jobParams = new HashMap<String,Map<String,InputParamController>>(2); /** Create an empty factory. * * <p> * Using this constructor, no {@link JobThread} can be created. * You have to add some in {@link #jobThreads} for each job list you have to support. * The parameters of each job/job-list can be listed in {@link #jobParams}. * </p> */ protected ConfigurableUWSFactory(){} /** * Create and initialize a UWS factory thanks to properties coming from a UWS configuration file. * * <p>The following properties are supported by this constructor:</p> * <ul> * <li>{@link UWSConfiguration#KEY_REQUEST_PARSER KEY_REQUEST_PARSER}</li> * <li>{@link UWSConfiguration#REGEXP_JOB_THREAD KEY_REGEXP_JOB_THREAD}</li> * <li>{@link UWSConfiguration#REGEXP_PARAMETERS KEY_REGEXP_PARAMETERS}</li> * <li>{@link UWSConfiguration#REGEXP_DEFAULT_EXEC_DURATION KEY_REGEXP_DEFAULT_EXEC_DURATION}</li> * <li>{@link UWSConfiguration#REGEXP_MAX_EXEC_DURATION KEY_REGEXP_MAX_EXEC_DURATION}</li> * <li>{@link UWSConfiguration#REGEXP_DEFAULT_DESTRUCTION_INTERVAL KEY_REGEXP_DEFAULT_DESTRUCTION_INTERVAL}</li> * <li>{@link UWSConfiguration#KEY_REGEXP_MAX_DESTRUCTION_INTERVAL KEY_REGEXP_MAX_DESTRUCTION_INTERVAL}</li> * </ul> * * @param uwsConfig Configuration of this factory. * * @throws UWSException If the initialization fails. */ public ConfigurableUWSFactory(final Properties uwsConfig) throws UWSException{ /* 1. Extract the RequestParser */ String propValue = getProperty(uwsConfig, KEY_REQUEST_PARSER); if (propValue != null) constructorRequestParser = fetchConstructor(propValue, KEY_REQUEST_PARSER, RequestParser.class, new Class<?>[]{UWSFileManager.class}); /* 2. Extract information (job thread + job parameters + exec duration + destruction time) about all job lists */ String propName, jlName = null; DurationParamController durationController = new DurationParamController(); @SuppressWarnings("unchecked") Enumeration<String> propNames = (Enumeration<String>)uwsConfig.propertyNames(); while(propNames.hasMoreElements()){ propName = propNames.nextElement(); // Set job thread: if (propName.matches(REGEXP_JOB_THREAD)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); jobThreads.put(jlName, fetchConstructor(propValue, propName, JobThread.class, new Class<?>[]{UWSJob.class})); } // Set expected job parameters: else if (propName.matches(REGEXP_PARAMETERS)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); initParameters(jlName, propValue); } // Set the default execution duration: else if (propName.matches(REGEXP_DEFAULT_EXEC_DURATION)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); try{ // Get map of all controllers for this job list: Map<String,InputParamController> mapControllers; if (jobParams.containsKey(jlName)) mapControllers = jobParams.get(jlName); else mapControllers = new HashMap<String,InputParamController>(); // Get its execution duration controller: ExecutionDurationController controller; if (mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION) != null && mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION) instanceof ExecutionDurationController) controller = (ExecutionDurationController)mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION); else controller = new ExecutionDurationController(); // Set the default execution duration: controller.setDefaultExecutionDuration(durationController.parseDuration(propValue) / 1000); // parseDuration(...) returns a duration in ms while executionDuration must be in seconds // Update the map of controllers for this job list: mapControllers.put(UWSJob.PARAM_EXECUTION_DURATION, controller); // Update the map of all job lists' controllers: jobParams.put(jlName, mapControllers); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the default execution duration: \"" + propValue + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the default execution duration! Cause: " + pe.getMessage()); } } // Set the maximum execution duration: else if (propName.matches(REGEXP_MAX_EXEC_DURATION)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); try{ // Get map of all controllers for this job list: Map<String,InputParamController> mapControllers; if (jobParams.containsKey(jlName)) mapControllers = jobParams.get(jlName); else mapControllers = new HashMap<String,InputParamController>(); // Get its execution duration controller: ExecutionDurationController controller; if (mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION) != null && mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION) instanceof ExecutionDurationController) controller = (ExecutionDurationController)mapControllers.get(UWSJob.PARAM_EXECUTION_DURATION); else controller = new ExecutionDurationController(); // Set the maximum execution duration: controller.setMaxExecutionDuration(durationController.parseDuration(propValue) / 1000); // parseDuration(...) returns a duration in ms while executionDuration must be in seconds // Update the map of controllers for this job list: mapControllers.put(UWSJob.PARAM_EXECUTION_DURATION, controller); // Update the map of all job lists' controllers: jobParams.put(jlName, mapControllers); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the maximum execution duration: \"" + propValue + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the maximum execution duration! Cause: " + pe.getMessage()); } } // Set the default destruction time: else if (propName.matches(REGEXP_DEFAULT_DESTRUCTION_INTERVAL)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); try{ // Get map of all controllers for this job list: Map<String,InputParamController> mapControllers; if (jobParams.containsKey(jlName)) mapControllers = jobParams.get(jlName); else mapControllers = new HashMap<String,InputParamController>(); // Get its destruction time controller: DestructionTimeController controller; if (mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME) != null && mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME) instanceof DestructionTimeController) controller = (DestructionTimeController)mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME); else controller = new DestructionTimeController(); // Set the default destruction time: controller.setDefaultDestructionInterval((int)durationController.parseDuration(propValue)); // Update the map of controllers for this job list: mapControllers.put(UWSJob.PARAM_DESTRUCTION_TIME, controller); // Update the map of all job lists' controllers: jobParams.put(jlName, mapControllers); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the default destruction time: \"" + propValue + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the default destruction time! Cause: " + pe.getMessage()); } } // Set the maximum destruction time: else if (propName.matches(KEY_REGEXP_MAX_DESTRUCTION_INTERVAL)){ jlName = extractJobListName(propName); propValue = getProperty(uwsConfig, propName); try{ // Get map of all controllers for this job list: Map<String,InputParamController> mapControllers; if (jobParams.containsKey(jlName)) mapControllers = jobParams.get(jlName); else mapControllers = new HashMap<String,InputParamController>(); // Get its destruction time controller: DestructionTimeController controller; if (mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME) != null && mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME) instanceof DestructionTimeController) controller = (DestructionTimeController)mapControllers.get(UWSJob.PARAM_DESTRUCTION_TIME); else controller = new DestructionTimeController(); // Set the maximum destruction time: controller.setMaxDestructionInterval((int)durationController.parseDuration(propValue)); // Update the map of controllers for this job list: mapControllers.put(UWSJob.PARAM_DESTRUCTION_TIME, controller); // Update the map of all job lists' controllers: jobParams.put(jlName, mapControllers); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the maximum destruction time: \"" + propValue + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the maximum destruction time! Cause: " + pe.getMessage()); } } } } /** * Regular Expression of a job parameters list. * * <p>The following parameter types are supported:</p> * <ul> * <li><em>Just a parameter name (i.e. no controller):</em> * <pre>\s*([^,\[\]]*)\s*(,(.*))?</pre> * <p>Example: <code>param1</code></p> * <ul> * <li><em>group(16) = </em>parameter name</li> * <li><em>group(18) = </em>all other parameters (without the leading comma)</li> * </ul> * </li> * <li><em>A parameter name and the class of an {@link InputParamController}:</em> * <pre>\s*\[([^,]+),(\{[^\}]*\})\s*\]\s*(,(.*))?</pre> * <p>Example: <code>[param1, {aPackage.MyCustomController}]</code></p> * <ul> * <li><em>group(2) = </em>parameter name</li> * <li><em>group(4) = </em>controller class name</li> * </ul> * </li> * <li><em>A parameter name and description of a string controller:</em> * <pre>\s*\[([^,]+),([^,]*),\s*(string)\s*,\s*"([^,]*)"\s*,\s* /(([^\/]|//)*)/(i)?\s*\]\s*(,(.*))?</pre> * <p>Example: <code>[param1, true, string, "default", /mySuperRegexp/i]</code></p> * <ul> * <li><em>group(2) = </em>parameter name</li> * <li><em>group(5) = </em>a boolean expression (yes, y, true, t) to indicate whether the parameter can be modified by the user</li> * <li><em>group(11) = </em><code>string</code></li> * <li><em>group(12) = </em>default value (it must be provided between brackets as in the example above)</li> * <li><em>group(13) = </em>the regular expression</li> * <li><em>group(15) = </em><code>i</code> if the regular expression must be evaluated in a case insensitive manner</li> * </ul> * </li> * <li><em>A parameter name and description of a numeric controller:</em> * <pre>\s*\[([^,]+),([^,]*),\s*(numeric)\s*,([^,]*),([^,]*),([^,]*)\s*\]\s*(,(.*))?</pre> * <p>Example: <code>[param1, true, numeric, 10, 0, 20]</code></p> * <ul> * <li><em>group(2) = </em>parameter name</li> * <li><em>group(5) = </em>a boolean expression (yes, y, true, t) to indicate whether the parameter can be modified by the user</li> * <li><em>group(7) = </em><code>numeric</code></li> * <li><em>group(8) = </em>default value ; only a numeric value (floating number or not ; negative or not) will be allowed after the expression has been parsed</li> * <li><em>group(9) = </em>minimum value ; only a numeric value (floating number or not ; negative or not) will be allowed after the expression has been parsed</li> * <li><em>group(10) = </em>maximum value ; only a numeric value (floating number or not ; negative or not) will be allowed after the expression has been parsed</li> * </ul> * </li> * <li><em>A parameter name and description of a duration controller:</em> * <pre>\s*\[([^,]+),([^,]*),\s*(duration)\s*,([^,]*),([^,]*),([^,]*)\s*\]\s*(,(.*))?</pre> * <p>Example: <code>[param1, true, numeric, 10, 0, 20]</code></p> * <ul> * <li><em>group(2) = </em>parameter name</li> * <li><em>group(5) = </em>a boolean expression (yes, y, true, t) to indicate whether the parameter can be modified by the user</li> * <li><em>group(7) = </em><code>numeric</code></li> * <li><em>group(8) = </em>default value</li> * <li><em>group(9) = </em>minimum value</li> * <li><em>group(10) = </em>maximum value</li> * </ul> * <p>The default, minimum and maximum value must a positive integer value followed eventually by a unit. If no unit is specified, the default is <code>milliseconds</code>. * See below for all supported units:</p> * <ul> * <li>milliseconds, ms</li> * <li>seconds, sec, s</li> * <li>minutes, min, m</li> * <li>hours, h</li> * <li>days, D</li> * <li>weeks, W</li> * <li>months, M</li> * <li>years, Y</li> * </ul> * </li> * </ul> */ protected static final Pattern PATTERN_PARAMETER = Pattern.compile("\\s*(\\[([^,]+),(\\s*(\\{[^\\}]*\\})|([^,]*),(\\s*(numeric|duration)\\s*,([^,]*),([^,]*),([^,]*)|\\s*(string)\\s*,\\s*\"([^\"]*)\"\\s*,\\s*/(([^/]|//)*)/(i)?))\\s*\\]|([^,\\[\\]]*))\\s*(,(.*))?", Pattern.CASE_INSENSITIVE); /** * Parse the given list of parameters + their limits/controller and update the list of parameters for the specified job list. * * <p> * The given string is parsed using {@link #PATTERN_PARAMETER}. The expected syntax of one item of this list is explained * in the javadoc of {@link #PATTERN_PARAMETER}. * </p> * * <p> * If just a parameter name is given, it is anyway added to the map of parameters of the specified job list, but with a <code>null</code> * {@link InputParamController}. The idea is to indicate the parameter is expected with this name, but there is no specific restriction on its value. * </p> * * @param jlName Name of the job list for which the given list of parameters is expected. * @param propValue String expressing the list of expected parameters (and eventually their limits/controller). * * @throws UWSException If the syntax of a parameter description is incorrect. */ protected void initParameters(final String jlName, final String propValue) throws UWSException{ // Get the existing list of parameters, if any; /* Note: it is possible if the same property key is found more than once in a property file. * In this case, the second list of parameters should update the first one. */ Map<String,InputParamController> jlParameters = jobParams.get(jlName); // If no list of controllers exists, create an empty one: if (jlParameters == null) jlParameters = new HashMap<String,InputParamController>(); int indParameter = 1; Matcher matcher; String remaining = propValue; String paramName, temp; boolean modif = true; while(remaining != null && remaining.trim().length() > 0){ // Apply the regular expression: matcher = PATTERN_PARAMETER.matcher(remaining); if (!matcher.matches()) throw new UWSException("Incorrect parameter list syntax from the parameter N°" + indParameter + ": " + remaining); // CASE: no controller specified if (matcher.group(16) != null){ // Fetch the parameter name: paramName = matcher.group(16).trim(); // Check the name: /* a parameter name must NOT be empty */ if (paramName.length() > 0){ /* a parameter name must NOT contain any space character */ if (!paramName.replaceFirst("\\s", "_").equals(paramName)) throw new UWSException("Incorrect syntax for the parameter name \"" + paramName + "\"! Space characters are forbidden."); else jlParameters.put(paramName, null); } }else{ // Fetch the parameter name: paramName = matcher.group(2).trim(); // Check the name: /* a parameter name must NOT be empty */ if (paramName.length() == 0) throw new UWSException("Missing name for the parameter N°" + indParameter + "!"); /* a parameter name must NOT contain any space character */ else if (!paramName.replaceFirst("\\s", "_").equals(paramName)) throw new UWSException("Incorrect syntax for the parameter name \"" + paramName + "\"! Space characters are forbidden."); // CASE: CUSTOM CONTROLLER if (matcher.group(4) != null){ jlParameters.put(paramName, newInstance(matcher.group(4), jlName + "." + UWSConfiguration.KEY_PARAMETERS, InputParamController.class, new Class<?>[0], new Object[0])); } // CASE: STRING/NUMERIC/DURATION else{ // Fetch the modification flag: temp = matcher.group(5).trim(); if (temp.length() == 0 || temp.matches("(?i)(true|t|yes|y)")) modif = true; else modif = false; // CASE: STRING if (matcher.group(11) != null){ // Create the controller: StringParamController controller = new StringParamController(paramName); // Set its modification flag: controller.allowModification(modif); // Set its default value, if any: if (matcher.group(12).length() > 0) controller.setDefaultValue(matcher.group(12)); // Set the regular expression: if (matcher.group(13).length() > 0) controller.setRegExp((matcher.group(15) != null ? "(?i)" : "") + matcher.group(13)); // Add the controller: jlParameters.put(paramName, controller); } // CASE: NUMERIC/DURATION else if (matcher.group(7) != null){ // CASE: NUMERIC if (matcher.group(7).trim().equalsIgnoreCase("numeric")){ // Create the controller: NumericParamController controller = new NumericParamController(); // Set its modification flag: controller.allowModification(modif); // Set the default value: if (matcher.group(8).trim().length() > 0){ try{ controller.setDefault(Double.parseDouble(matcher.group(8).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the default value of the parameter \"" + paramName + "\": \"" + matcher.group(8).trim() + "\"!"); } } // Set the minimum value: if (matcher.group(9).trim().length() > 0){ try{ controller.setMinimum(Double.parseDouble(matcher.group(9).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the minimum value of the parameter \"" + paramName + "\": \"" + matcher.group(9).trim() + "\"!"); } } // Set the maximum value: if (matcher.group(10).trim().length() > 0){ try{ controller.setMaximum(Double.parseDouble(matcher.group(10).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the maximum value of the parameter \"" + paramName + "\": \"" + matcher.group(10).trim() + "\"!"); } } // Add the controller: jlParameters.put(paramName, controller); } // CASE: DURATION else{ // Create the controller: DurationParamController controller = new DurationParamController(); // Set its modification flag: controller.allowModification(modif); // Set the default value: if (matcher.group(8).trim().length() > 0){ try{ controller.setDefault(controller.parseDuration(matcher.group(8).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the default value of the parameter \"" + paramName + "\": \"" + matcher.group(8).trim() + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the default duration of the parameter \"" + paramName + "\"! Cause: " + pe.getMessage()); } } // Set the minimum value: if (matcher.group(9).trim().length() > 0){ try{ controller.setMinimum(controller.parseDuration(matcher.group(9).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the minimum value of the parameter \"" + paramName + "\": \"" + matcher.group(9).trim() + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the minimu duration of the parameter \"" + paramName + "\"! Cause: " + pe.getMessage()); } } // Set the maximum value: if (matcher.group(10).trim().length() > 0){ try{ controller.setMaximum(controller.parseDuration(matcher.group(10).trim())); }catch(NumberFormatException nfe){ throw new UWSException("Wrong numeric format for the maximum value of the parameter \"" + paramName + "\": \"" + matcher.group(10).trim() + "\"!"); }catch(ParseException pe){ throw new UWSException("Incorrect syntax for the maximum duration of the parameter \"" + paramName + "\"! Cause: " + pe.getMessage()); } } // Add the controller: jlParameters.put(paramName, controller); } } } } // Read the other parameters: remaining = matcher.group(18); indParameter++; modif = true; } // Add this new list of parameters: if (jlParameters.size() > 0) jobParams.put(jlName, jlParameters); } @Override public JobThread createJobThread(final UWSJob jobDescription) throws UWSException{ // No job => No thread ^^ if (jobDescription == null) return null; // If the job is not inside a job list, it is impossible to know which instance of JobThread to create => Error! else if (jobDescription.getJobList() == null) throw new UWSException("Job without job list! Impossible to create a thread for the job \"" + jobDescription.getJobId() + "\"."); // Extract the job list name: String jlName = jobDescription.getJobList().getName(); // If no class is associated with this job list name, no JobThread can be created => Error! if (jlName == null || jobThreads.get(jlName) == null) throw new UWSException("No thread associated with jobs of the job list \"" + jlName + "\"! Impossible to create a thread for the job \"" + jobDescription.getJobId() + "\"."); // Get the constructor: Constructor<? extends JobThread> threadConstructor = jobThreads.get(jlName); try{ // Create the JobThread: return threadConstructor.newInstance(jobDescription); }catch(InstantiationException ie){ throw new UWSException("Impossible to create an instance of an abstract class: \"" + threadConstructor.getDeclaringClass().getName() + "\"!"); }catch(InvocationTargetException ite){ if (ite.getCause() != null){ if (ite.getCause() instanceof UWSException) throw (UWSException)ite.getCause(); else throw new UWSException(ite.getCause()); }else throw new UWSException(ite); }catch(Exception ex){ throw new UWSException(UWSException.NOT_FOUND, ex, "Impossible to create the thread " + threadConstructor.getDeclaringClass().getName() + " for the job \"" + jobDescription.getJobId() + "\"!"); } } @Override public UWSJob createJob(final HttpServletRequest request, final JobOwner user) throws UWSException{ // Extract the HTTP request ID (the job ID should be the same, if not already used by another job): String requestID = null; if (request != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) instanceof String) requestID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID).toString(); // Create the job: return new UWSJob(user, createUWSParameters(request), requestID); } @Override public UWSJob createJob(String jobID, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{ return new UWSJob(jobID, owner, params, quote, startTime, endTime, results, error); } @Override public UWSParameters createUWSParameters(final Map<String,Object> params) throws UWSException{ return new UWSParameters(params); } @Override public UWSParameters createUWSParameters(final HttpServletRequest req) throws UWSException{ UWSUrl url = new UWSUrl(req); if (url.getJobListName() != null && jobParams.get(url.getJobListName()) != null){ return new UWSParameters(req, jobParams.get(url.getJobListName()).keySet(), jobParams.get(url.getJobListName())); }else return new UWSParameters(req); } @Override public RequestParser createRequestParser(final UWSFileManager fileManager) throws UWSException{ if (constructorRequestParser == null) return new UWSRequestParser(fileManager); else{ try{ return constructorRequestParser.newInstance(fileManager); }catch(InstantiationException ie){ throw new UWSException("Impossible to create an instance of an abstract class: \"" + constructorRequestParser.getDeclaringClass().getName() + "\"!"); }catch(InvocationTargetException ite){ if (ite.getCause() != null){ if (ite.getCause() instanceof UWSException) throw (UWSException)ite.getCause(); else throw new UWSException(ite.getCause()); }else throw new UWSException(ite); }catch(Exception ex){ throw new UWSException(UWSException.NOT_FOUND, ex, "Impossible to create the request parser " + constructorRequestParser.getDeclaringClass().getName() + "\"!"); } } } }