diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java index 36984fac6ae7b123c3899bea600228f91148db59..203a2021ed9750d944f160b05b90a83931368dad 100644 --- a/src/tap/AbstractTAPFactory.java +++ b/src/tap/AbstractTAPFactory.java @@ -53,7 +53,7 @@ import adql.query.ADQLQuery; * Only the functions related with the database connection stay abstract. * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (10/2014) + * @version 2.0 (11/2014) */ public abstract class AbstractTAPFactory extends TAPFactory { @@ -277,7 +277,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { @Override public TAPParameters createTAPParameters(final HttpServletRequest request) throws TAPException{ try{ - return new TAPParameters(request, service, getExpectedAdditionalParameters(), getInputParamControllers()); + return new TAPParameters(request, service); }catch(UWSException ue){ throw new TAPException(ue); } @@ -296,7 +296,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { @Override public TAPParameters createTAPParameters(final Map<String,Object> params) throws TAPException{ try{ - return new TAPParameters(service, params, getExpectedAdditionalParameters(), getInputParamControllers()); + return new TAPParameters(service, params); }catch(UWSException ue){ throw new TAPException(ue); } diff --git a/src/tap/TAPFactory.java b/src/tap/TAPFactory.java index de00df9c065c5c2730171ce07fda95c280269343..f0ba06fdb83ef58d24d1a5cd285483dc2a5b5fb1 100644 --- a/src/tap/TAPFactory.java +++ b/src/tap/TAPFactory.java @@ -37,7 +37,7 @@ import uws.job.Result; import uws.job.UWSJob; import uws.job.parameters.UWSParameters; import uws.job.user.JobOwner; -import uws.service.AbstractUWSFactory; +import uws.service.UWSFactory; import uws.service.UWSService; import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; @@ -59,9 +59,9 @@ import adql.query.ADQLQuery; * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (11/2014) */ -public abstract class TAPFactory extends AbstractUWSFactory { +public abstract class TAPFactory implements UWSFactory { /** Connection to the TAP service ; it provides all important service configuration information. */ protected final ServiceConnection service; diff --git a/src/tap/parameters/FormatController.java b/src/tap/parameters/FormatController.java index 93e654b69fc6635e436739ff85f05dfd5f75022f..a48339ac7cded7d65d250ae96285964f046d543b 100644 --- a/src/tap/parameters/FormatController.java +++ b/src/tap/parameters/FormatController.java @@ -78,7 +78,7 @@ public class FormatController implements InputParamController { @Override public Object check(Object format) throws UWSException{ if (format == null) - return null; + return getDefault(); if (format instanceof String){ String strFormat = ((String)format).trim(); diff --git a/src/tap/parameters/MaxRecController.java b/src/tap/parameters/MaxRecController.java index 6aa4694653467239a045ad31eb3d91409ca8016e..da3b94bef54e19b2a1ad4d3849140aa02c8d0060 100644 --- a/src/tap/parameters/MaxRecController.java +++ b/src/tap/parameters/MaxRecController.java @@ -32,17 +32,24 @@ import uws.job.parameters.InputParamController; * * <p><i>Note: * By default, this parameter can be modified by anyone without any limitation. + * The default and maximum value is set by default to {@link TAPJob#UNLIMITED_MAX_REC}. + * </i></p> + * + * <p><i>Note: + * The special value 0 means that just the metadata of the result must be returned. + * Considering the meaning of this value, it will not be considered as an {@link TAPJob#UNLIMITED_MAX_REC}, + * but like a valid value. The maximum value can then be also 0. * </i></p> * * <p>The logic of the output limit is set in this class. Here it is:</p> * <ul> - * <li>If no value is specified by the TAP client, none is returned.</li> - * <li>If no default value is provided, no default limitation is set (={@link TAPJob#UNLIMITED_MAX_REC}).</li> - * <li>If no maximum value is provided, there is no output limit (={@link TAPJob#UNLIMITED_MAX_REC}).</li> + * <li>If no value is specified by the TAP client, the default value is returned.</li> + * <li>If no default value is provided, the maximum output limit is returned.</li> + * <li>If no maximum value is provided, there is no limit (={@link TAPJob#UNLIMITED_MAX_REC}).</li> * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (11/2014) */ public class MaxRecController implements InputParamController { @@ -63,13 +70,18 @@ public class MaxRecController implements InputParamController { @Override public final Object getDefault(){ - // If a default output limit is set by the TAP service connection, return it: + // Get the default output limit: + int defaultLimit = TAPJob.UNLIMITED_MAX_REC; if (service.getOutputLimit() != null && service.getOutputLimit().length >= 2 && service.getOutputLimitType() != null && service.getOutputLimitType().length == service.getOutputLimit().length){ if (service.getOutputLimit()[0] > 0 && service.getOutputLimitType()[0] == LimitUnit.rows) - return service.getOutputLimit()[0]; + defaultLimit = service.getOutputLimit()[0]; } - // Otherwise, return no limitation: - return TAPJob.UNLIMITED_MAX_REC; + + // Get the maximum output limit, for comparison: + int maxLimit = getMaxOutputLimit(); + + // Ensure the default limit is less or equal the maximum limit: + return (defaultLimit < 0 || (maxLimit >= 0 && defaultLimit > maxLimit)) ? maxLimit : defaultLimit; } /** @@ -91,7 +103,7 @@ public class MaxRecController implements InputParamController { public Object check(Object value) throws UWSException{ // If no limit is provided by the TAP client, none is returned: if (value == null) - return null; + return getDefault(); // Parse the provided limit: int maxOutputLimit = getMaxOutputLimit(); @@ -109,11 +121,11 @@ public class MaxRecController implements InputParamController { throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Wrong type for the parameter \"maxrec\": class \"" + value.getClass().getName() + "\"! It should be an integer or a string containing only an integer value."); // A negative output limit is considered as an unlimited output limit: - if (maxRec < TAPJob.UNLIMITED_MAX_REC) + if (maxRec < 0) maxRec = TAPJob.UNLIMITED_MAX_REC; // If the limit is greater than the maximum one, an exception is thrown: - if (maxRec == TAPJob.UNLIMITED_MAX_REC || maxRec > maxOutputLimit) + if (maxRec < 0 || (maxOutputLimit >= 0 && maxRec > maxOutputLimit)) maxRec = maxOutputLimit; return maxRec; diff --git a/src/tap/parameters/TAPDestructionTimeController.java b/src/tap/parameters/TAPDestructionTimeController.java index 0c3a40325042c4081cdc2f85fff623a69d71956e..e5742edfd27eb6c0a79eaef3a5e64a73c31fe6eb 100644 --- a/src/tap/parameters/TAPDestructionTimeController.java +++ b/src/tap/parameters/TAPDestructionTimeController.java @@ -27,7 +27,6 @@ import java.util.Date; import tap.ServiceConnection; import uws.ISO8601Format; import uws.UWSException; -import uws.job.UWSJob; import uws.job.parameters.DestructionTimeController.DateField; import uws.job.parameters.InputParamController; @@ -40,8 +39,15 @@ import uws.job.parameters.InputParamController; * There is no default value (that means jobs may stay forever). * </i></p> * + * <p>The logic of the destruction time is set in this class. Here it is:</p> + * <ul> + * <li>If no value is specified by the UWS client, the default value is returned.</li> + * <li>If no default value is provided, the maximum destruction date is returned.</li> + * <li>If no maximum value is provided, there is no destruction.</li> + * </ul> + * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (11/2014) */ public class TAPDestructionTimeController implements InputParamController { @@ -90,17 +96,23 @@ public class TAPDestructionTimeController implements InputParamController { @Override public final Object getDefault(){ + // Get the default period and ensure it is always less or equal the maximum period, if any: int defaultPeriod = getDefaultRetentionPeriod(); + int maxPeriod = getMaxRetentionPeriod(); + if (defaultPeriod <= 0 || (maxPeriod > 0 && defaultPeriod > maxPeriod)) + defaultPeriod = maxPeriod; + + // Build and return the date: if (defaultPeriod > 0){ Calendar date = Calendar.getInstance(); try{ date.add(DateField.SECOND.getFieldIndex(), defaultPeriod); return date.getTime(); - }catch(ArrayIndexOutOfBoundsException ex){ - return null; - } - }else - return null; + }catch(ArrayIndexOutOfBoundsException ex){} + } + + // If no default period is specified or if an exception occurs, the maximum destruction time must be returned: + return getMaxDestructionTime(); } /** @@ -123,24 +135,29 @@ public class TAPDestructionTimeController implements InputParamController { * @return The maximum destruction time (<i>null</i> means that jobs may stay forever). */ public final Date getMaxDestructionTime(){ + // Get the maximum period: int maxPeriod = getMaxRetentionPeriod(); + + // Build and return the maximum destruction date: if (maxPeriod > 0){ Calendar date = Calendar.getInstance(); try{ date.add(DateField.SECOND.getFieldIndex(), maxPeriod); return date.getTime(); - }catch(ArrayIndexOutOfBoundsException ex){ - return null; - } - }else - return null; + }catch(ArrayIndexOutOfBoundsException ex){} + } + + // If no maximum period is specified or if an exception occurs, NULL must be returned: + return null; } @Override public Object check(Object value) throws UWSException{ + // If NULL value, return the default value: if (value == null) - return null; + return getDefault(); + // Parse the given date: Date date = null; if (value instanceof Date) date = (Date)value; @@ -154,10 +171,12 @@ public class TAPDestructionTimeController implements InputParamController { }else throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Wrong type for the parameter \"destruction\": class \"" + value.getClass().getName() + "\"! It should be a Date or a string containing a date formatted in ISO8601 (\"yyyy-MM-dd'T'hh:mm:ss[.sss]['Z'|[+|-]hh:mm]\", fields inside brackets are optional)."); + // Ensure the date is before the maximum destruction time (from now): Date maxDate = getMaxDestructionTime(); if (maxDate != null && date.after(maxDate)) - throw new UWSException(UWSException.BAD_REQUEST, "The TAP service limits the destruction interval (since now) to " + getMaxRetentionPeriod() + " s !"); + date = maxDate; + // Return the parsed date return date; } diff --git a/src/tap/parameters/TAPExecutionDurationController.java b/src/tap/parameters/TAPExecutionDurationController.java index 63d15ba28de6cbb1ea1a0c13e037f6603eea3921..6c158d0dac8571bcee5e65d9bc8212e87c0691b4 100644 --- a/src/tap/parameters/TAPExecutionDurationController.java +++ b/src/tap/parameters/TAPExecutionDurationController.java @@ -34,8 +34,15 @@ import uws.job.parameters.InputParamController; * The default value is {@link TAPJob#UNLIMITED_DURATION}. * </i></p> * + * <p>The logic of the execution duration is set in this class. Here it is:</p> + * <ul> + * <li>If no value is specified by the TAP client, the default value is returned.</li> + * <li>If no default value is provided, the maximum duration is returned.</li> + * <li>If no maximum value is provided, there is no limit (={@link TAPJob#UNLIMITED_DURATION}).</li> + * </ul> + * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (11/2014) */ public class TAPExecutionDurationController implements InputParamController { @@ -70,11 +77,14 @@ public class TAPExecutionDurationController implements InputParamController { @Override public final Object getDefault(){ - if (service.getExecutionDuration() != null && service.getExecutionDuration().length >= 2){ - if (service.getExecutionDuration()[0] > 0) - return service.getExecutionDuration()[0]; - } - return TAPJob.UNLIMITED_DURATION; + // Get the default value from the service connection: + long defaultVal = TAPJob.UNLIMITED_DURATION; + if (service.getExecutionDuration() != null && service.getExecutionDuration().length >= 2) + defaultVal = service.getExecutionDuration()[0]; + + // The default value is also limited by the maximum value if any: + long maxVal = getMaxDuration(); + return (defaultVal <= 0 || (maxVal > 0 && defaultVal > maxVal)) ? maxVal : defaultVal; } /** @@ -91,15 +101,20 @@ public class TAPExecutionDurationController implements InputParamController { } @Override - public Object check(Object value) throws UWSException{ + public Object check(final Object value) throws UWSException{ + // If no value, return the default one: if (value == null) - return null; + return getDefault(); - long defaultDuration = ((Long)getDefault()).longValue(), maxDuration = getMaxDuration(); - Long duration; + // Get the default and maximum durations for comparison: + long defaultDuration = (Long)getDefault(), maxDuration = getMaxDuration(); + // Parse the given duration: + Long duration; if (value instanceof Long) duration = (Long)value; + else if (value instanceof Integer) + duration = (long)(Integer)value; else if (value instanceof String){ try{ duration = Long.parseLong((String)value); @@ -109,10 +124,13 @@ public class TAPExecutionDurationController implements InputParamController { }else throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Wrong type for the parameter \"executionduration\": class \"" + value.getClass().getName() + "\"! It should be long or a string containing only a long value."); - if (duration < TAPJob.UNLIMITED_DURATION) + // A negative value must be considered as an unlimited duration: + if (duration <= 0) duration = TAPJob.UNLIMITED_DURATION; - else if (maxDuration > TAPJob.UNLIMITED_DURATION && duration > maxDuration) - throw new UWSException(UWSException.BAD_REQUEST, "The TAP service limits the execution duration to maximum " + maxDuration + " seconds !"); + + // Ensure the given value is less than the maximum duration: + if (maxDuration > 0 && (duration > maxDuration || duration <= 0)) + duration = maxDuration; return duration; } diff --git a/src/tap/parameters/TAPParameters.java b/src/tap/parameters/TAPParameters.java index 6eb4f0936bc064396a551acdf551928e97f9f248..21a2e69010c1ab438acb870788a4c871b9f0ced7 100644 --- a/src/tap/parameters/TAPParameters.java +++ b/src/tap/parameters/TAPParameters.java @@ -16,15 +16,17 @@ package tap.parameters; * You should have received a copy of the GNU Lesser General Public License * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * - * Copyright 2012 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS) + * Copyright 2012,2014 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.io.File; import java.io.IOException; -import java.util.Collection; +import java.util.Arrays; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -44,15 +46,13 @@ import com.oreilly.servlet.multipart.FileRenamePolicy; /** * This class describes all defined parameters of a TAP request. * - * @author Grégory Mantelet (CDS) - * @version 06/2012 + * @author Grégory Mantelet (CDS;ARI) + * @version 2.0 (11/2014) */ public class TAPParameters extends UWSParameters { - /** - * All the TAP parameters. - */ - protected static final String[] TAP_PARAMETERS = new String[]{TAPJob.PARAM_REQUEST,TAPJob.PARAM_LANGUAGE,TAPJob.PARAM_VERSION,TAPJob.PARAM_FORMAT,TAPJob.PARAM_QUERY,TAPJob.PARAM_MAX_REC,TAPJob.PARAM_UPLOAD}; + /** All the TAP parameters. */ + protected static final List<String> TAP_PARAMETERS = Arrays.asList(new String[]{TAPJob.PARAM_REQUEST,TAPJob.PARAM_LANGUAGE,TAPJob.PARAM_VERSION,TAPJob.PARAM_FORMAT,TAPJob.PARAM_QUERY,TAPJob.PARAM_MAX_REC,TAPJob.PARAM_UPLOAD}); /** Part of HTTP content type header. */ public static final String MULTIPART = "multipart/"; @@ -61,21 +61,13 @@ public class TAPParameters extends UWSParameters { protected TableLoader[] tablesToUpload = null; public TAPParameters(final ServiceConnection service){ - this(service, null, null); - } - - public TAPParameters(final ServiceConnection service, final Collection<String> expectedAdditionalParams, final Map<String,InputParamController> inputParamControllers){ - super(expectedAdditionalParams, inputParamControllers); + super(TAP_PARAMETERS, null); initDefaultTAPControllers(service); } public TAPParameters(final HttpServletRequest request, final ServiceConnection service) throws UWSException, TAPException{ - this(request, service, null, null); - } + this(service); - @SuppressWarnings("unchecked") - public TAPParameters(final HttpServletRequest request, final ServiceConnection service, final Collection<String> expectedAdditionalParams, final Map<String,InputParamController> inputParamControllers) throws UWSException, TAPException{ - this(service, expectedAdditionalParams, inputParamControllers); MultipartRequest multipart = null; // Multipart HTTP parameters: @@ -91,6 +83,7 @@ public class TAPParameters extends UWSParameters { return new File(file.getParentFile(), (new Date()).toString() + "_" + file.getName()); } }); + @SuppressWarnings("unchecked") Enumeration<String> e = multipart.getParameterNames(); while(e.hasMoreElements()){ String param = e.nextElement(); @@ -124,11 +117,7 @@ public class TAPParameters extends UWSParameters { } public TAPParameters(final ServiceConnection service, final Map<String,Object> params) throws UWSException, TAPException{ - this(service, params, null, null); - } - - public TAPParameters(final ServiceConnection service, final Map<String,Object> params, final Collection<String> expectedAdditionalParams, final Map<String,InputParamController> inputParamControllers) throws UWSException, TAPException{ - super(params, expectedAdditionalParams, inputParamControllers); + super(params, TAP_PARAMETERS, null); initDefaultTAPControllers(service); } @@ -137,44 +126,16 @@ public class TAPParameters extends UWSParameters { return new HashMap<String,InputParamController>(10); } - protected < R > void initDefaultTAPControllers(final ServiceConnection service){ - if (!mapParamControllers.containsKey(TAPJob.PARAM_EXECUTION_DURATION)) - mapParamControllers.put(TAPJob.PARAM_EXECUTION_DURATION, new TAPExecutionDurationController(service)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_DESTRUCTION_TIME)) - mapParamControllers.put(TAPJob.PARAM_DESTRUCTION_TIME, new TAPDestructionTimeController(service)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_REQUEST)) - mapParamControllers.put(TAPJob.PARAM_REQUEST, new StringParamController(TAPJob.PARAM_REQUEST, null, new String[]{TAPJob.REQUEST_DO_QUERY,TAPJob.REQUEST_GET_CAPABILITIES}, true)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_LANGUAGE)) - mapParamControllers.put(TAPJob.PARAM_LANGUAGE, new StringParamController(TAPJob.PARAM_LANGUAGE, TAPJob.LANG_ADQL, null, true)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_VERSION)) - mapParamControllers.put(TAPJob.PARAM_VERSION, new StringParamController(TAPJob.PARAM_VERSION, TAPJob.VERSION_1_0, new String[]{TAPJob.VERSION_1_0}, true)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_QUERY)) - mapParamControllers.put(TAPJob.PARAM_QUERY, new StringParamController(TAPJob.PARAM_QUERY)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_UPLOAD)) - mapParamControllers.put(TAPJob.PARAM_UPLOAD, new StringParamController(TAPJob.PARAM_UPLOAD)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_FORMAT)) - mapParamControllers.put(TAPJob.PARAM_FORMAT, new FormatController(service)); - - if (!mapParamControllers.containsKey(TAPJob.PARAM_MAX_REC)) - mapParamControllers.put(TAPJob.PARAM_MAX_REC, new MaxRecController(service)); - } - - @Override - protected String normalizeParamName(String name){ - if (name != null && !name.trim().isEmpty()){ - for(String tapParam : TAP_PARAMETERS){ - if (name.equalsIgnoreCase(tapParam)) - return tapParam; - } - } - return super.normalizeParamName(name); + protected void initDefaultTAPControllers(final ServiceConnection service){ + mapParamControllers.put(TAPJob.PARAM_EXECUTION_DURATION, new TAPExecutionDurationController(service)); + mapParamControllers.put(TAPJob.PARAM_DESTRUCTION_TIME, new TAPDestructionTimeController(service)); + mapParamControllers.put(TAPJob.PARAM_REQUEST, new StringParamController(TAPJob.PARAM_REQUEST, null, new String[]{TAPJob.REQUEST_DO_QUERY,TAPJob.REQUEST_GET_CAPABILITIES}, true)); + mapParamControllers.put(TAPJob.PARAM_LANGUAGE, new StringParamController(TAPJob.PARAM_LANGUAGE, TAPJob.LANG_ADQL, null, true)); + mapParamControllers.put(TAPJob.PARAM_VERSION, new StringParamController(TAPJob.PARAM_VERSION, TAPJob.VERSION_1_0, new String[]{TAPJob.VERSION_1_0}, true)); + mapParamControllers.put(TAPJob.PARAM_QUERY, new StringParamController(TAPJob.PARAM_QUERY)); + mapParamControllers.put(TAPJob.PARAM_UPLOAD, new StringParamController(TAPJob.PARAM_UPLOAD)); + mapParamControllers.put(TAPJob.PARAM_FORMAT, new FormatController(service)); + mapParamControllers.put(TAPJob.PARAM_MAX_REC, new MaxRecController(service)); } @Override diff --git a/src/uws/job/JobThread.java b/src/uws/job/JobThread.java index 538e0ba47ce63de9d0d2d2ebf575a54775202246..5f2bef35e71f1d9f15d1301bbbc8de1dd7fda62d 100644 --- a/src/uws/job/JobThread.java +++ b/src/uws/job/JobThread.java @@ -282,7 +282,7 @@ public abstract class JobThread extends Thread { setError(error); }catch(IOException ioe){ - job.getLogger().logThread(LogLevel.ERROR, this, "SET_ERROR", "The stack trace of a UWSException had not been written !", ioe); + job.getLogger().logThread(LogLevel.ERROR, this, "SET_ERROR", "The stack trace of a UWSException had not been written!", ioe); setError(new ErrorSummary(ue.getMessage(), ue.getUWSErrorType())); } } diff --git a/src/uws/job/parameters/DestructionTimeController.java b/src/uws/job/parameters/DestructionTimeController.java index 35c94435e397e5cf5035a3605d8368bdc5141b2b..bf8699919bdd600347494613fe7052ca5afc2c74 100644 --- a/src/uws/job/parameters/DestructionTimeController.java +++ b/src/uws/job/parameters/DestructionTimeController.java @@ -34,19 +34,24 @@ import uws.UWSException; * Moreover you can indicate whether the destruction time of jobs can be modified by the user or not. * </p> * - * <p> - * <i><u>Notes:</u> - * <ul> - * <li>By default, the destruction time can be modified by anyone without any limitation. - * There is no default value (that means jobs may stay forever).</li> - * <li>You can specify a destruction time (default or maximum value) in two ways: - * by an exact date-time or by an interval of time from the initialization (expressed in the second, minutes, hours, days, months or years).</li> - * </ul> - * </i> - * </p> + * <p><i><u>Notes:</u> + * <ul> + * <li>By default, the destruction time can be modified by anyone without any limitation. + * There is no default value (that means jobs may stay forever).</li> + * <li>You can specify a destruction time (default or maximum value) in two ways: + * by an exact date-time or by an interval of time from the initialization (expressed in the second, minutes, hours, days, months or years).</li> + * </ul> + * </i></p> + * + * <p>The logic of the destruction time is set in this class. Here it is:</p> + * <ul> + * <li>If no value is specified by the UWS client, the default value is returned.</li> + * <li>If no default value is provided, the maximum destruction date is returned.</li> + * <li>If no maximum value is provided, there is no destruction.</li> + * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (09/2014) + * @version 4.1 (11/2014) */ public class DestructionTimeController implements InputParamController, Serializable { private static final long serialVersionUID = 1L; @@ -55,7 +60,7 @@ public class DestructionTimeController implements InputParamController, Serializ * Represents a date/time field. * * @author Grégory Mantelet (CDS) - * @version 02/2011 + * @version 4.0 (02/2011) * * @see Calendar */ @@ -94,10 +99,12 @@ public class DestructionTimeController implements InputParamController, Serializ protected boolean allowModification = true; @Override - public Object check(Object value) throws UWSException{ + public Object check(final Object value) throws UWSException{ + // If no value, return the default one: if (value == null) - return null; + return getDefault(); + // Otherwise, parse the date: Date date = null; if (value instanceof Date) date = (Date)value; @@ -111,16 +118,19 @@ public class DestructionTimeController implements InputParamController, Serializ }else throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Wrong type for the destruction time parameter: class \"" + value.getClass().getName() + "\"! It should be a Date or a string containing a date formatted in IS8601 (\"yyyy-MM-dd'T'hh:mm:ss[.sss]['Z'|[+|-]hh:mm]\", fields inside brackets are optional)."); + // Compare it to the maximum destruction time: if after, set the date to the maximum allowed date: Date maxDate = getMaxDestructionTime(); if (maxDate != null && date.after(maxDate)) - throw new UWSException(UWSException.BAD_REQUEST, "The UWS limits " + ((defaultInterval > NO_INTERVAL) ? ("the DESTRUCTION INTERVAL (since now) to " + maxInterval + " " + maxIntervalField.name().toLowerCase() + "s") : ("the DESTRUCTION TIME to " + maxDate)) + " !"); + date = maxDate; + // Return the parsed date: return date; } @Override public Object getDefault(){ - return getDefaultDestructionTime(); + Date defaultDate = getDefaultDestructionTime(); + return (defaultDate == null) ? getMaxDestructionTime() : defaultDate; } /* ***************** */ @@ -306,9 +316,15 @@ public class DestructionTimeController implements InputParamController, Serializ * @param timeField The unit of the interval (<i>null</i> means the job may stay forever). */ public final void setMaxDestructionInterval(int maxDestructionInterval, DateField timeField){ - this.maxInterval = maxDestructionInterval; - maxIntervalField = timeField; - maxTime = null; + if (maxDestructionInterval <= 0 || timeField == null){ + this.maxInterval = NO_INTERVAL; + maxIntervalField = null; + maxTime = null; + }else{ + this.maxInterval = maxDestructionInterval; + maxIntervalField = timeField; + maxTime = null; + } } /** diff --git a/src/uws/job/parameters/ExecutionDurationController.java b/src/uws/job/parameters/ExecutionDurationController.java index 45cd04bed2872db8d7451e06b538a95b02eb484c..670d02f9556b9969546ff4f6166fcf19b1477d64 100644 --- a/src/uws/job/parameters/ExecutionDurationController.java +++ b/src/uws/job/parameters/ExecutionDurationController.java @@ -31,32 +31,63 @@ import uws.job.UWSJob; * Moreover you can indicate whether the execution duration of jobs can be modified by the user or not. * </p> * - * <p> - * <i><u>Note:</u> - * By default, the execution duration can be modified by anyone without any limitation. - * The default value is {@link UWSJob#UNLIMITED_DURATION}. - * </i> - * </p> + * <p><i><u>Note:</u> the execution duration is always expressed <b>in seconds</b>.</i></p> + * + * <p><i><u>Note:</u> + * By default, the execution duration can be modified by anyone without any limitation. + * The default and maximum value is {@link UWSJob#UNLIMITED_DURATION}. + * </i></p> + * + * <p>The logic of the execution duration is set in this class. Here it is:</p> + * <ul> + * <li>If no value is specified by the UWS client, the default value is returned.</li> + * <li>If no default value is provided, the maximum duration is returned.</li> + * <li>If no maximum value is provided, there is no limit (={@link UWSJob#UNLIMITED_DURATION}).</li> + * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (09/2014) + * @version 4.1 (11/2014) */ public class ExecutionDurationController implements InputParamController, Serializable { private static final long serialVersionUID = 1L; - /** The default duration. */ + /** The default duration (in seconds). */ protected long defaultDuration = UWSJob.UNLIMITED_DURATION; - /** The maximum duration. */ + /** The maximum duration (in seconds). */ protected long maxDuration = UWSJob.UNLIMITED_DURATION; /** Indicates whether the execution duration of jobs can be modified. */ protected boolean allowModification = true; - public ExecutionDurationController(){ - ; - } + /** + * <p>Create a controller for the execution duration. + * By default, there is no maximum value and the default duration is {@link UWSJob#UNLIMITED_DURATION}.</p> + * + * <p> + * A default and/or maximum value can be set after creation using {@link #setDefaultExecutionDuration(long)} + * and {@link #setMaxExecutionDuration(long)}. By default this parameter can always be modified, but it can + * be forbidden using {@link #allowModification(boolean)}. + * </p> + */ + public ExecutionDurationController(){} + /** + * <p>Create a controller for the execution duration. + * The default and the maximum duration are initialized with the given parameters. + * The third parameter allows also to forbid the modification of the execution duration by the user, + * if set to <i>false</i>.</p> + * + * <p> + * A default and/or maximum value can be modified after creation using {@link #setDefaultExecutionDuration(long)} + * and {@link #setMaxExecutionDuration(long)}. The flag telling whether this parameter can be modified by the user + * can be changed using {@link #allowModification(boolean)}. + * </p> + * + * @param defaultDuration Duration (in seconds) set by default to a job, when none is specified. + * @param maxDuration Maximum duration (in seconds) that can be set. If a greater value is provided by the user, an exception will be thrown by {@link #check(Object)}. + * @param allowModification <i>true</i> to allow the user to modify this value when creating a job, <i>false</i> otherwise. + */ public ExecutionDurationController(final long defaultDuration, final long maxDuration, final boolean allowModification){ setDefaultExecutionDuration(defaultDuration); setMaxExecutionDuration(maxDuration); @@ -65,17 +96,21 @@ public class ExecutionDurationController implements InputParamController, Serial @Override public Object getDefault(){ - return defaultDuration; + return (defaultDuration > 0) ? defaultDuration : getMaxExecutionDuration(); } @Override - public Object check(Object value) throws UWSException{ + public Object check(final Object value) throws UWSException{ + // If no value, return the default one: if (value == null) - return null; + return getDefault(); + // Otherwise, parse the given duration: Long duration = null; if (value instanceof Long) duration = (Long)value; + else if (value instanceof Integer) + duration = (long)(Integer)value; else if (value instanceof String){ String strValue = (String)value; try{ @@ -86,10 +121,13 @@ public class ExecutionDurationController implements InputParamController, Serial }else throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Wrong type for the maximum duration parameter: class \"" + value.getClass().getName() + "\"! It should be long or a string containing only a long value."); - if (duration < UWSJob.UNLIMITED_DURATION) + // If the duration is negative or zero, set it to UNLIMITED: + if (duration <= 0) duration = UWSJob.UNLIMITED_DURATION; - else if (maxDuration > UWSJob.UNLIMITED_DURATION && duration > maxDuration) - throw new UWSException(UWSException.BAD_REQUEST, "The UWS limits the execution duration to maximum " + maxDuration + " seconds !"); + + // Set the maximum duration if the duration is greater than the maximum value: + if (maxDuration > 0 && (duration > maxDuration || duration <= 0)) + duration = maxDuration; return duration; } @@ -100,16 +138,19 @@ public class ExecutionDurationController implements InputParamController, Serial /** * Gets the default execution duration. * - * @return The default execution duration <i>(0 or less mean an unlimited duration)</i>. + * @return The default execution duration (in seconds) <i>(0 or less mean an unlimited duration)</i>. + * + * @deprecated This function is completely equivalent to {@link #getDefault()}. */ + @Deprecated public final long getDefaultExecutionDuration(){ - return defaultDuration; + return (Long)getDefault(); } /** * Sets the default execution duration. * - * @param defaultExecutionDuration The new default execution duration <i>({@link UWSJob#UNLIMITED_DURATION}, 0 or a negative value mean an unlimited duration)</i>. + * @param defaultExecutionDuration The new default execution duration (in seconds) <i>({@link UWSJob#UNLIMITED_DURATION}, 0 or a negative value mean an unlimited duration)</i>. */ public final boolean setDefaultExecutionDuration(long defaultExecutionDuration){ defaultExecutionDuration = (defaultExecutionDuration <= 0) ? UWSJob.UNLIMITED_DURATION : defaultExecutionDuration; @@ -125,7 +166,7 @@ public class ExecutionDurationController implements InputParamController, Serial /** * Gets the maximum execution duration. * - * @return The maximum execution duration <i>(0 or less mean an unlimited duration)</i>. + * @return The maximum execution duration (in seconds) <i>(0 or less mean an unlimited duration)</i>. */ public final long getMaxExecutionDuration(){ return maxDuration; @@ -134,7 +175,7 @@ public class ExecutionDurationController implements InputParamController, Serial /** * Sets the maximum execution duration. * - * @param maxExecutionDuration The maximum execution duration <i>({@link UWSJob#UNLIMITED_DURATION}, 0 or a negative value mean an unlimited duration)</i>. + * @param maxExecutionDuration The maximum execution duration (in seconds) <i>({@link UWSJob#UNLIMITED_DURATION}, 0 or a negative value mean an unlimited duration)</i>. */ public final void setMaxExecutionDuration(long maxExecutionDuration){ maxDuration = (maxExecutionDuration <= 0) ? UWSJob.UNLIMITED_DURATION : maxExecutionDuration; diff --git a/src/uws/job/parameters/InputParamController.java b/src/uws/job/parameters/InputParamController.java index 72e6a33b45580ed3d2fa1320f4ddd6e0265f3c7c..5cf47ee792b4d85f72bc1a1696dafa3bcbdda473 100644 --- a/src/uws/job/parameters/InputParamController.java +++ b/src/uws/job/parameters/InputParamController.java @@ -25,6 +25,7 @@ import uws.UWSException; * <p>Lets controlling an input parameter of a UWS job.</p> * * @author Grégory Mantelet (CDS) + * @version 4.0 */ public interface InputParamController { diff --git a/src/uws/job/parameters/UWSParameters.java b/src/uws/job/parameters/UWSParameters.java index d41afda5fb5fc86861f799ce75d780e124f75809..43b91256883130535a199baa3ff1bd8a0625731b 100644 --- a/src/uws/job/parameters/UWSParameters.java +++ b/src/uws/job/parameters/UWSParameters.java @@ -193,7 +193,6 @@ public class UWSParameters implements Iterable<Entry<String,Object>> { * * @see #UWSParameters(Collection, Map) */ - @SuppressWarnings("unchecked") public UWSParameters(final HttpServletRequest request, final Collection<String> expectedAdditionalParams, final Map<String,InputParamController> inputParamControllers) throws UWSException{ this(expectedAdditionalParams, inputParamControllers); diff --git a/src/uws/service/UWS.java b/src/uws/service/UWS.java index 492b17b668b2f33c1c74eadd8c2fcdec64bf679f..a81e2968d2df3a4d42114bd105bde6c1904edd80 100644 --- a/src/uws/service/UWS.java +++ b/src/uws/service/UWS.java @@ -20,14 +20,10 @@ package uws.service; */ import uws.UWSException; - import uws.job.JobList; - import uws.job.serializer.UWSSerializer; - import uws.service.backup.UWSBackupManager; import uws.service.file.UWSFileManager; - import uws.service.log.UWSLog; /** @@ -183,7 +179,7 @@ public interface UWS extends Iterable<JobList> { /* ******************* */ /** - * + * TODO JAVADOC TO WRITE! * @return */ public UserIdentifier getUserIdentifier(); diff --git a/test/tap/parameters/ServiceConnectionOfTest.java b/test/tap/parameters/ServiceConnectionOfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..30a56ee1a127c430203b60e5b03656c00ac43cc7 --- /dev/null +++ b/test/tap/parameters/ServiceConnectionOfTest.java @@ -0,0 +1,161 @@ +package tap.parameters; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import tap.ServiceConnection; +import tap.TAPFactory; +import tap.TAPJob; +import tap.file.TAPFileManager; +import tap.formatter.FITSFormat; +import tap.formatter.OutputFormat; +import tap.formatter.SVFormat; +import tap.formatter.VOTableFormat; +import tap.log.TAPLog; +import tap.metadata.TAPMetadata; +import uws.service.UserIdentifier; +import adql.db.FunctionDef; + +public class ServiceConnectionOfTest implements ServiceConnection { + + private int[] retentionPeriod = new int[]{-1,-1}; + private int[] executionDuration = new int[]{(int)TAPJob.UNLIMITED_DURATION,(int)TAPJob.UNLIMITED_DURATION}; + private int[] outputLimit = new int[]{TAPJob.UNLIMITED_MAX_REC,TAPJob.UNLIMITED_MAX_REC}; + private List<OutputFormat> outputFormats = Arrays.asList(new OutputFormat[]{new VOTableFormat(this),new SVFormat(this, SVFormat.COMMA_SEPARATOR),new FITSFormat(this)}); + + @Override + public String getProviderName(){ + return null; + } + + @Override + public String getProviderDescription(){ + return null; + } + + @Override + public boolean isAvailable(){ + return true; + } + + @Override + public String getAvailability(){ + return null; + } + + @Override + public int[] getRetentionPeriod(){ + return retentionPeriod; + } + + public void setRetentionPeriod(final int defaultVal, final int maxVal){ + retentionPeriod[0] = defaultVal; + retentionPeriod[1] = maxVal; + } + + @Override + public int[] getExecutionDuration(){ + return executionDuration; + } + + public void setExecutionDuration(final int defaultVal, final int maxVal){ + executionDuration[0] = defaultVal; + executionDuration[1] = maxVal; + } + + @Override + public int[] getOutputLimit(){ + return outputLimit; + } + + public void setOutputLimit(final int defaultVal, final int maxVal){ + outputLimit[0] = defaultVal; + outputLimit[1] = maxVal; + } + + @Override + public LimitUnit[] getOutputLimitType(){ + return new LimitUnit[]{LimitUnit.rows,LimitUnit.rows}; + } + + @Override + public UserIdentifier getUserIdentifier(){ + return null; + } + + @Override + public boolean uploadEnabled(){ + return false; + } + + @Override + public int[] getUploadLimit(){ + return null; + } + + @Override + public LimitUnit[] getUploadLimitType(){ + return null; + } + + @Override + public int getMaxUploadSize(){ + return 0; + } + + @Override + public TAPMetadata getTAPMetadata(){ + return null; + } + + @Override + public Collection<String> getCoordinateSystems(){ + return null; + } + + @Override + public Collection<String> getGeometries(){ + return null; + } + + @Override + public Collection<FunctionDef> getUDFs(){ + return null; + } + + @Override + public int getNbMaxAsyncJobs(){ + return 0; + } + + @Override + public TAPLog getLogger(){ + return null; + } + + @Override + public TAPFactory getFactory(){ + return null; + } + + @Override + public TAPFileManager getFileManager(){ + return null; + } + + @Override + public Iterator<OutputFormat> getOutputFormats(){ + return outputFormats.iterator(); + } + + @Override + public OutputFormat getOutputFormat(String mimeOrAlias){ + for(OutputFormat f : outputFormats) + if (f.getMimeType().equalsIgnoreCase(mimeOrAlias) || f.getShortMimeType().equalsIgnoreCase(mimeOrAlias)) + return f; + return null; + } + +} \ No newline at end of file diff --git a/test/tap/parameters/TestFormatController.java b/test/tap/parameters/TestFormatController.java new file mode 100644 index 0000000000000000000000000000000000000000..50d0bb4cd8a8e46204aa8b191ce1d43adbe6ea87 --- /dev/null +++ b/test/tap/parameters/TestFormatController.java @@ -0,0 +1,89 @@ +package tap.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import tap.TAPJob; +import uws.UWSException; + +public class TestFormatController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + FormatController controller = new FormatController(service); + + try{ + assertEquals(controller.getDefault(), controller.check(null)); + assertEquals(controller.getDefault(), controller.check("")); + assertEquals(controller.getDefault(), controller.check(" ")); + assertEquals(controller.getDefault(), controller.check(" ")); + assertEquals(controller.getDefault(), controller.check(" ")); + assertEquals("votable", controller.check("votable")); + assertEquals("application/x-votable+xml", controller.check("application/x-votable+xml")); + assertEquals("csv", controller.check("csv")); + assertEquals("fits", controller.check("fits")); + }catch(Exception ex){ + ex.printStackTrace(); + fail(); + } + + try{ + controller.check("toto"); + }catch(Exception ex){ + assertTrue(ex instanceof UWSException); + assertTrue(ex.getMessage().startsWith("Unknown value for the parameter \"format\": \"toto\". It should be ")); + } + + try{ + controller.check("application/xml"); + }catch(Exception ex){ + assertTrue(ex instanceof UWSException); + assertTrue(ex.getMessage().startsWith("Unknown value for the parameter \"format\": \"application/xml\". It should be ")); + } + } + + @Test + public void testGetDefault(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + FormatController controller = new FormatController(service); + + assertEquals(TAPJob.FORMAT_VOTABLE, controller.getDefault()); + } + + @Test + public void testAllowModification(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + FormatController controller = new FormatController(service); + + // By default, user modification of the destruction time is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + +} diff --git a/test/tap/parameters/TestMaxRecController.java b/test/tap/parameters/TestMaxRecController.java new file mode 100644 index 0000000000000000000000000000000000000000..613a2f92c04b7ecd38485d5050a0fef352303523 --- /dev/null +++ b/test/tap/parameters/TestMaxRecController.java @@ -0,0 +1,142 @@ +package tap.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import tap.TAPJob; + +public class TestMaxRecController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + MaxRecController controller = new MaxRecController(service); + + try{ + // A NULL limit will always return an unlimited duration: + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.check(null)); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.check(-1)); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.check(-123)); + + // A 0 value, means that only the metadata of the result must be returned (without executing the query); + // this value should stay like that: + assertEquals(0, controller.check(0)); + + // By default, the controller has no limit on the output limit, so let's try with a limit of 1000000 rows: + assertEquals(1000000, controller.check(1000000)); + + // With just a default output limit (of 100 rows): + service.setOutputLimit(100, -1); + assertEquals(100, controller.check(null)); + assertEquals(0, controller.check(0)); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.check(-1)); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.check(TAPJob.UNLIMITED_MAX_REC)); + + // With just a maximum output limit (of 10000 rows): + service.setOutputLimit(-1, 10000); + assertEquals(10000, controller.check(null)); + assertEquals(0, controller.check(0)); + assertEquals(60, controller.check(60)); + assertEquals(10000, controller.check(-1)); + assertEquals(10000, controller.check(TAPJob.UNLIMITED_MAX_REC)); + assertEquals(10000, controller.check(10001)); + + // With a default (100 rows) AND a maximum (10000 rows) output limit: + service.setOutputLimit(100, 10000); + assertEquals(100, controller.check(null)); + assertEquals(0, controller.check(0)); + assertEquals(10, controller.check(10)); + assertEquals(600, controller.check(600)); + assertEquals(10000, controller.check(10000)); + assertEquals(10000, controller.check(-1)); + assertEquals(10000, controller.check(TAPJob.UNLIMITED_MAX_REC)); + assertEquals(10000, controller.check(10001)); + + }catch(Exception t){ + t.printStackTrace(); + fail(); + } + } + + @Test + public void testGetDefault(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + MaxRecController controller = new MaxRecController(service); + + // By default, when nothing is set, the default output limit is UNLIMITED: + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getDefault()); + + // With no duration, the default output limit should remain UNLIMITED: + service.setOutputLimit(TAPJob.UNLIMITED_MAX_REC, -1); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getDefault()); + + // With a negative limit, the output limit should also be UNLIMITED: + service.setOutputLimit(-1, -1); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getDefault()); + + // With an output limit of 100 rows: + service.setOutputLimit(100, -1); + assertEquals(100, controller.getDefault()); + + // The default value must always be less than the maximum value: + service.setOutputLimit(600, 300); + assertEquals(300, controller.getDefault()); + } + + @Test + public void testGetMaxExecutionDuration(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + MaxRecController controller = new MaxRecController(service); + + // By default, when nothing is set, the maximum output limit is UNLIMITED: + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getMaxOutputLimit()); + + // With no duration, the maximum output limit should remain UNLIMITED: + service.setOutputLimit(-1, TAPJob.UNLIMITED_MAX_REC); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getMaxOutputLimit()); + + // With a negative limit, the output limit should also be UNLIMITED: + service.setOutputLimit(-1, -1); + assertEquals(TAPJob.UNLIMITED_MAX_REC, controller.getMaxOutputLimit()); + + // With an output limit of 10000 rows: + service.setOutputLimit(-1, 10000); + assertEquals(10000, controller.getMaxOutputLimit()); + } + + @Test + public void testAllowModification(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + MaxRecController controller = new MaxRecController(service); + + // By default, user modification of the destruction time is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + +} diff --git a/test/tap/parameters/TestTAPDestructionTimeController.java b/test/tap/parameters/TestTAPDestructionTimeController.java new file mode 100644 index 0000000000000000000000000000000000000000..73453af6d9e94e8741f848ee1a706cdd8c60a754 --- /dev/null +++ b/test/tap/parameters/TestTAPDestructionTimeController.java @@ -0,0 +1,187 @@ +package tap.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Calendar; +import java.util.Date; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import uws.ISO8601Format; + +public class TestTAPDestructionTimeController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPDestructionTimeController controller = new TAPDestructionTimeController(service); + Calendar calendar = Calendar.getInstance(); + + try{ + // A NULL destruction time will always return NULL: + assertNull(controller.check(null)); + + // By default, the controller has no limit on the destruction time, so let's try with a destruction in 100 years: + calendar.add(Calendar.YEAR, 100); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + checkDate(calendar.getTime(), controller.check(ISO8601Format.format(calendar.getTimeInMillis()))); + + // With just a default destruction time (of 10 minutes): + service.setRetentionPeriod(600, -1); + Calendar defaultTime = Calendar.getInstance(); + defaultTime.add(Calendar.MINUTE, 10); + checkDate(defaultTime.getTime(), controller.check(null)); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + + // With just a maximum destruction time (of 1 hour): + service.setRetentionPeriod(0, 3600); + Calendar maxTime = Calendar.getInstance(); + maxTime.add(Calendar.HOUR, 1); + checkDate(maxTime.getTime(), controller.check(null)); + checkDate(defaultTime.getTime(), controller.check(defaultTime.getTime())); + checkDate(maxTime.getTime(), controller.check(calendar.getTime())); + + // With a default (10 minutes) AND a maximum (1 hour) destruction time: + service.setRetentionPeriod(600, 3600); + checkDate(defaultTime.getTime(), controller.check(null)); + checkDate(maxTime.getTime(), controller.check(calendar.getTime())); + calendar = Calendar.getInstance(); + calendar.add(Calendar.MINUTE, 30); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + + }catch(Exception t){ + t.printStackTrace(); + fail(); + } + } + + @Test + public void testGetDefault(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPDestructionTimeController controller = new TAPDestructionTimeController(service); + + // By default, when nothing is set, the default destruction time is NULL (the job will never be destroyed): + assertNull(controller.getDefault()); + + // With no interval, the default destruction time should remain NULL (the job will never be destroyed): + service.setRetentionPeriod(0, -1); + assertNull(controller.getDefault()); + + // With a negative interval, the destruction time should also be NULL: + service.setRetentionPeriod(-1, -1); + assertNull(controller.getDefault()); + + // With a destruction interval of 100 minutes: + Calendar calendar = Calendar.getInstance(); + service.setRetentionPeriod(6000, -1); + calendar.add(Calendar.MINUTE, 100); + checkDate(calendar.getTime(), controller.getDefault()); + + // With a destruction interval of 100 seconds: + service.setRetentionPeriod(100, -1); + calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, 100); + checkDate(calendar.getTime(), controller.getDefault()); + + // With a destruction interval of 1 week: + service.setRetentionPeriod(7 * 24 * 3600, -1); + calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 7); + checkDate(calendar.getTime(), controller.getDefault()); + } + + @Test + public void testGetMaxDestructionTime(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPDestructionTimeController controller = new TAPDestructionTimeController(service); + + // By default, when nothing is set, the maximum destruction time is NULL (the job will never be destroyed): + assertNull(controller.getMaxDestructionTime()); + + // With no interval, the maximum destruction time should remain NULL (the job will never be destroyed): + service.setRetentionPeriod(-1, 0); + assertNull(controller.getMaxDestructionTime()); + + // With a negative interval, the destruction time should also be NULL: + service.setRetentionPeriod(-1, -1); + assertNull(controller.getMaxDestructionTime()); + + // With a destruction interval of 100 minutes: + Calendar calendar = Calendar.getInstance(); + service.setRetentionPeriod(-1, 6000); + calendar.add(Calendar.MINUTE, 100); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + + // With a destruction interval of 100 seconds: + service.setRetentionPeriod(-1, 100); + calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, 100); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + + // With a destruction interval of 1 week: + service.setRetentionPeriod(-1, 7 * 24 * 3600); + calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 7); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + } + + @Test + public void testAllowModification(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPDestructionTimeController controller = new TAPDestructionTimeController(service); + + // By default, user modification of the destruction time is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + + private void checkDate(final Date expected, final Object val){ + assertTrue(val instanceof Date); + + if (expected != null && val != null){ + Calendar cexpected = Calendar.getInstance(), cval = Calendar.getInstance(); + cexpected.setTime(expected); + cval.setTime((Date)val); + + try{ + assertEquals(cexpected.get(Calendar.DAY_OF_MONTH), cval.get(Calendar.DAY_OF_MONTH)); + assertEquals(cexpected.get(Calendar.MONTH), cval.get(Calendar.MONTH)); + assertEquals(cexpected.get(Calendar.YEAR), cval.get(Calendar.YEAR)); + assertEquals(cexpected.get(Calendar.HOUR), cval.get(Calendar.HOUR)); + assertEquals(cexpected.get(Calendar.MINUTE), cval.get(Calendar.MINUTE)); + assertEquals(cexpected.get(Calendar.SECOND), cval.get(Calendar.SECOND)); + }catch(AssertionError e){ + fail("Expected <" + expected + "> but was <" + val + ">"); + } + }else if (expected == null && val == null) + return; + else + fail("Expected <" + expected + "> but was <" + val + ">"); + } + +} diff --git a/test/tap/parameters/TestTAPExecutionDurationController.java b/test/tap/parameters/TestTAPExecutionDurationController.java new file mode 100644 index 0000000000000000000000000000000000000000..446c58e07098072a29e7fbcea479bf2c5545e68e --- /dev/null +++ b/test/tap/parameters/TestTAPExecutionDurationController.java @@ -0,0 +1,136 @@ +package tap.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import tap.TAPJob; + +public class TestTAPExecutionDurationController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPExecutionDurationController controller = new TAPExecutionDurationController(service); + + try{ + // A NULL duration will always return an unlimited duration: + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(null)); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(0)); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(-1)); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(-123)); + + // By default, the controller has no limit on the execution duration, so let's try with a duration of 1e6 seconds: + assertEquals(1000000L, controller.check(1000000)); + + // With just a default execution duration (of 10 minutes): + service.setExecutionDuration(600, -1); + assertEquals(600L, controller.check(null)); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(-1)); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.check(TAPJob.UNLIMITED_DURATION)); + + // With just a maximum execution duration (of 1 hour): + service.setExecutionDuration(-1, 3600); + assertEquals(3600L, controller.check(null)); + assertEquals(60L, controller.check(60)); + assertEquals(3600L, controller.check(-1)); + assertEquals(3600L, controller.check(TAPJob.UNLIMITED_DURATION)); + assertEquals(3600L, controller.check(3601)); + + // With a default (10 minutes) AND a maximum (1 hour) execution duration: + service.setExecutionDuration(600, 3600); + assertEquals(600L, controller.check(null)); + assertEquals(10L, controller.check(10)); + assertEquals(600L, controller.check(600)); + assertEquals(3600L, controller.check(3600)); + assertEquals(3600L, controller.check(-1)); + assertEquals(3600L, controller.check(TAPJob.UNLIMITED_DURATION)); + assertEquals(3600L, controller.check(3601)); + + }catch(Exception t){ + t.printStackTrace(); + fail(); + } + } + + @Test + public void testGetDefault(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPExecutionDurationController controller = new TAPExecutionDurationController(service); + + // By default, when nothing is set, the default execution duration is UNLIMITED: + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getDefault()); + + // With no duration, the default execution duration should remain UNLIMITED: + service.setExecutionDuration((int)TAPJob.UNLIMITED_DURATION, -1); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getDefault()); + + // With a negative duration, the execution duration should also be UNLIMITED: + service.setExecutionDuration(-1, -1); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getDefault()); + + // With an execution duration of 10 minutes: + service.setExecutionDuration(600, -1); + assertEquals(600L, controller.getDefault()); + + // The default value must always be less than the maximum value: + service.setExecutionDuration(600, 300); + assertEquals(300L, controller.getDefault()); + } + + @Test + public void testGetMaxExecutionDuration(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPExecutionDurationController controller = new TAPExecutionDurationController(service); + + // By default, when nothing is set, the maximum execution duration is UNLIMITED: + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getMaxDuration()); + + // With no duration, the maximum execution duration should remain UNLIMITED: + service.setExecutionDuration(-1, (int)TAPJob.UNLIMITED_DURATION); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getMaxDuration()); + + // With a negative duration, the execution duration should also be UNLIMITED: + service.setExecutionDuration(-1, -1); + assertEquals(TAPJob.UNLIMITED_DURATION, controller.getMaxDuration()); + + // With an execution duration of 10 minutes: + service.setExecutionDuration(-1, 600); + assertEquals(600L, controller.getMaxDuration()); + } + + @Test + public void testAllowModification(){ + ServiceConnectionOfTest service = new ServiceConnectionOfTest(); + TAPExecutionDurationController controller = new TAPExecutionDurationController(service); + + // By default, user modification of the execution duration is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + +} diff --git a/test/uws/job/parameters/TestDestructionTimeController.java b/test/uws/job/parameters/TestDestructionTimeController.java new file mode 100644 index 0000000000000000000000000000000000000000..a50d5eb1e40297c803e82cbc1da04c065520a243 --- /dev/null +++ b/test/uws/job/parameters/TestDestructionTimeController.java @@ -0,0 +1,186 @@ +package uws.job.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Calendar; +import java.util.Date; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import uws.ISO8601Format; +import uws.job.parameters.DestructionTimeController.DateField; + +public class TestDestructionTimeController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + DestructionTimeController controller = new DestructionTimeController(); + Calendar calendar = Calendar.getInstance(); + + try{ + // A NULL destruction time will always return NULL: + assertNull(controller.check(null)); + + // By default, the controller has no limit on the destruction time, so let's try with a destruction in 100 years: + calendar.add(Calendar.YEAR, 100); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + checkDate(calendar.getTime(), controller.check(ISO8601Format.format(calendar.getTimeInMillis()))); + + // With just a default destruction time (of 10 minutes): + controller.setDefaultDestructionInterval(10); + Calendar defaultTime = Calendar.getInstance(); + defaultTime.add(Calendar.MINUTE, 10); + checkDate(defaultTime.getTime(), controller.check(null)); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + + // With just a maximum destruction time (of 1 hour): + controller.setDefaultDestructionInterval(0); + controller.setMaxDestructionInterval(1, DateField.HOUR); + Calendar maxTime = Calendar.getInstance(); + maxTime.add(Calendar.HOUR, 1); + checkDate(maxTime.getTime(), controller.check(null)); + checkDate(defaultTime.getTime(), controller.check(defaultTime.getTime())); + checkDate(maxTime.getTime(), controller.check(calendar.getTime())); + + // With a default (10 minutes) AND a maximum (1 hour) destruction time: + controller.setDefaultDestructionInterval(10); + controller.setMaxDestructionInterval(1, DateField.HOUR); + checkDate(defaultTime.getTime(), controller.check(null)); + checkDate(maxTime.getTime(), controller.check(calendar.getTime())); + calendar = Calendar.getInstance(); + calendar.add(Calendar.MINUTE, 30); + checkDate(calendar.getTime(), controller.check(calendar.getTime())); + + }catch(Exception t){ + t.printStackTrace(); + fail(); + } + } + + @Test + public void testGetDefault(){ + DestructionTimeController controller = new DestructionTimeController(); + + // By default, when nothing is set, the default destruction time is NULL (the job will never be destroyed): + assertNull(controller.getDefault()); + + // With no interval, the default destruction time should remain NULL (the job will never be destroyed): + controller.setDefaultDestructionInterval(DestructionTimeController.NO_INTERVAL); + assertNull(controller.getDefault()); + + // With a negative interval, the destruction time should also be NULL: + controller.setDefaultDestructionInterval(-1); + assertNull(controller.getDefault()); + + // With a destruction interval of 100 minutes: + Calendar calendar = Calendar.getInstance(); + controller.setDefaultDestructionInterval(100); + calendar.add(Calendar.MINUTE, 100); + checkDate(calendar.getTime(), controller.getDefault()); + + // With a destruction interval of 100 seconds: + controller.setDefaultDestructionInterval(100, DateField.SECOND); + calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, 100); + checkDate(calendar.getTime(), controller.getDefault()); + + // With a destruction interval of 1 week: + controller.setDefaultDestructionInterval(7, DateField.DAY); + calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 7); + checkDate(calendar.getTime(), controller.getDefault()); + } + + @Test + public void testGetMaxDestructionTime(){ + DestructionTimeController controller = new DestructionTimeController(); + + // By default, when nothing is set, the maximum destruction time is NULL (the job will never be destroyed): + assertNull(controller.getMaxDestructionTime()); + + // With no interval, the maximum destruction time should remain NULL (the job will never be destroyed): + controller.setMaxDestructionInterval(DestructionTimeController.NO_INTERVAL); + assertNull(controller.getMaxDestructionTime()); + + // With a negative interval, the destruction time should also be NULL: + controller.setMaxDestructionInterval(-1); + assertNull(controller.getMaxDestructionTime()); + + // With a destruction interval of 100 minutes: + Calendar calendar = Calendar.getInstance(); + controller.setMaxDestructionInterval(100); + calendar.add(Calendar.MINUTE, 100); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + + // With a destruction interval of 100 seconds: + controller.setMaxDestructionInterval(100, DateField.SECOND); + calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, 100); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + + // With a destruction interval of 1 week: + controller.setMaxDestructionInterval(7, DateField.DAY); + calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 7); + checkDate(calendar.getTime(), controller.getMaxDestructionTime()); + } + + @Test + public void testAllowModification(){ + DestructionTimeController controller = new DestructionTimeController(); + + // By default, user modification of the destruction time is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + + private void checkDate(final Date expected, final Object val){ + assertTrue(val instanceof Date); + + if (expected != null && val != null){ + Calendar cexpected = Calendar.getInstance(), cval = Calendar.getInstance(); + cexpected.setTime(expected); + cval.setTime((Date)val); + + try{ + assertEquals(cexpected.get(Calendar.DAY_OF_MONTH), cval.get(Calendar.DAY_OF_MONTH)); + assertEquals(cexpected.get(Calendar.MONTH), cval.get(Calendar.MONTH)); + assertEquals(cexpected.get(Calendar.YEAR), cval.get(Calendar.YEAR)); + assertEquals(cexpected.get(Calendar.HOUR), cval.get(Calendar.HOUR)); + assertEquals(cexpected.get(Calendar.MINUTE), cval.get(Calendar.MINUTE)); + assertEquals(cexpected.get(Calendar.SECOND), cval.get(Calendar.SECOND)); + }catch(AssertionError e){ + fail("Expected <" + expected + "> but was <" + val + ">"); + } + }else if (expected == null && val == null) + return; + else + fail("Expected <" + expected + "> but was <" + val + ">"); + } + +} diff --git a/test/uws/job/parameters/TestExecutionDurationController.java b/test/uws/job/parameters/TestExecutionDurationController.java new file mode 100644 index 0000000000000000000000000000000000000000..65eef00017943d266fdd3dd27259537ef3815231 --- /dev/null +++ b/test/uws/job/parameters/TestExecutionDurationController.java @@ -0,0 +1,134 @@ +package uws.job.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import uws.job.UWSJob; + +public class TestExecutionDurationController { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testCheck(){ + ExecutionDurationController controller = new ExecutionDurationController(); + + try{ + // A NULL duration will always return an unlimited duration: + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(null)); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(0)); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(-1)); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(-123)); + + // By default, the controller has no limit on the execution duration, so let's try with a duration of 1e6 seconds: + assertEquals(1000000L, controller.check(1000000)); + + // With just a default execution duration (of 10 minutes): + controller.setDefaultExecutionDuration(600); + assertEquals(600L, controller.check(null)); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(-1)); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.check(UWSJob.UNLIMITED_DURATION)); + + // With just a maximum execution duration (of 1 hour): + controller.setDefaultExecutionDuration(-1); + controller.setMaxExecutionDuration(3600); + assertEquals(3600L, controller.check(null)); + assertEquals(60L, controller.check(60)); + assertEquals(3600L, controller.check(-1)); + assertEquals(3600L, controller.check(UWSJob.UNLIMITED_DURATION)); + assertEquals(3600L, controller.check(3601)); + + // With a default (10 minutes) AND a maximum (1 hour) execution duration: + controller.setDefaultExecutionDuration(600); + controller.setMaxExecutionDuration(3600); + assertEquals(600L, controller.check(null)); + assertEquals(10L, controller.check(10)); + assertEquals(600L, controller.check(600)); + assertEquals(3600L, controller.check(3600)); + assertEquals(3600L, controller.check(-1)); + assertEquals(3600L, controller.check(UWSJob.UNLIMITED_DURATION)); + assertEquals(3600L, controller.check(3601)); + + }catch(Exception t){ + t.printStackTrace(); + fail(); + } + } + + @Test + public void testGetDefault(){ + ExecutionDurationController controller = new ExecutionDurationController(); + + // By default, when nothing is set, the default execution duration is UNLIMITED: + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getDefault()); + + // With no duration, the default execution duration should remain UNLIMITED: + controller.setDefaultExecutionDuration(UWSJob.UNLIMITED_DURATION); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getDefault()); + + // With a negative duration, the execution duration should also be UNLIMITED: + controller.setDefaultExecutionDuration(-1); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getDefault()); + + // With an execution duration of 10 minutes: + controller.setDefaultExecutionDuration(600); + assertEquals(600L, controller.getDefault()); + + // The default value must always be less than the maximum value: + controller.setMaxExecutionDuration(300); + assertEquals(300L, controller.getDefault()); + } + + @Test + public void testGetMaxExecutionDuration(){ + ExecutionDurationController controller = new ExecutionDurationController(); + + // By default, when nothing is set, the maximum execution duration is UNLIMITED: + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getMaxExecutionDuration()); + + // With no duration, the maximum execution duration should remain UNLIMITED: + controller.setMaxExecutionDuration(UWSJob.UNLIMITED_DURATION); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getMaxExecutionDuration()); + + // With a negative duration, the execution duration should also be UNLIMITED: + controller.setMaxExecutionDuration(-1); + assertEquals(UWSJob.UNLIMITED_DURATION, controller.getMaxExecutionDuration()); + + // With an execution duration of 10 minutes: + controller.setMaxExecutionDuration(600); + assertEquals(600L, controller.getMaxExecutionDuration()); + } + + @Test + public void testAllowModification(){ + ExecutionDurationController controller = new ExecutionDurationController(); + + // By default, user modification of the execution duration is allowed: + assertTrue(controller.allowModification()); + + controller.allowModification(true); + assertTrue(controller.allowModification()); + + controller.allowModification(false); + assertFalse(controller.allowModification()); + } + +}