diff --git a/src/org/json/Json4Uws.java b/src/org/json/Json4Uws.java index e6a6b271b2f026bf1678231e58e3a0e9ad3ee4af..2549e0a0dbfbbd886758506ab99ab1c034720224 100644 --- a/src/org/json/Json4Uws.java +++ b/src/org/json/Json4Uws.java @@ -124,15 +124,16 @@ public final class Json4Uws { json.put("version", UWS.VERSION); json.put(UWSJob.PARAM_JOB_ID, job.getJobId()); json.put(UWSJob.PARAM_PHASE, job.getPhase()); + json.put(UWSJob.PARAM_RUN_ID, job.getRunId()); + if (job.getOwner() != null) + json.put(UWSJob.PARAM_OWNER, job.getOwner().getPseudo()); + json.put(UWSJob.PARAM_CREATION_TIME, ISO8601Format.format(job.getCreationTime())); if (reference){ if (jobsListUrl != null){ jobsListUrl.setJobId(job.getJobId()); json.put("href", jobsListUrl.getRequestURL()); } }else{ - json.put(UWSJob.PARAM_RUN_ID, job.getRunId()); - if (job.getOwner() != null) - json.put(UWSJob.PARAM_OWNER, job.getOwner().getPseudo()); json.put(UWSJob.PARAM_QUOTE, job.getQuote()); if (job.getStartTime() != null) json.put(UWSJob.PARAM_START_TIME, ISO8601Format.format(job.getStartTime())); diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java index e96636c5ac1a6511e7c2547994fbe22834027ee3..dbc0e7d38614dd2faac6a12a8d850bc72939dad4 100644 --- a/src/tap/AbstractTAPFactory.java +++ b/src/tap/AbstractTAPFactory.java @@ -2,21 +2,21 @@ package tap; /* * This file is part of TAPLibrary. - * + * * TAPLibrary 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. - * + * * TAPLibrary 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 TAPLibrary. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -28,6 +28,12 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import adql.db.DBChecker; +import adql.parser.ADQLParser; +import adql.parser.ADQLQueryFactory; +import adql.parser.ParseException; +import adql.parser.QueryChecker; +import adql.query.ADQLQuery; import tap.db.DBConnection; import tap.error.DefaultTAPErrorWriter; import tap.metadata.TAPMetadata; @@ -43,19 +49,13 @@ import uws.service.UWS; import uws.service.UWSService; import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; -import adql.db.DBChecker; -import adql.parser.ADQLParser; -import adql.parser.ADQLQueryFactory; -import adql.parser.ParseException; -import adql.parser.QueryChecker; -import adql.query.ADQLQuery; /** * Default implementation of most of the {@link TAPFactory} function. * Only the functions related with the database connection stay abstract. - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 2.1 (01/2016) + * @version 2.2 (09/2017) */ public abstract class AbstractTAPFactory extends TAPFactory { @@ -65,11 +65,11 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * Build a basic TAPFactory. * Nothing is done except setting the service connection. - * + * * @param service Configuration of the TAP service. <i>MUST NOT be NULL</i> - * + * * @throws NullPointerException If the given {@link ServiceConnection} is NULL. - * + * * @see AbstractTAPFactory#AbstractTAPFactory(ServiceConnection, ServiceErrorWriter) */ protected AbstractTAPFactory(ServiceConnection service) throws NullPointerException{ @@ -79,14 +79,14 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>Build a basic TAPFactory. * Nothing is done except setting the service connection and the given error writer.</p> - * + * * <p>Then the error writer will be used when creating a UWS service and a job thread.</p> - * + * * @param service Configuration of the TAP service. <i>MUST NOT be NULL</i> * @param errorWriter Object to use to format and write the errors for the user. - * + * * @throws NullPointerException If the given {@link ServiceConnection} is NULL. - * + * * @see TAPFactory#TAPFactory(ServiceConnection) */ protected AbstractTAPFactory(final ServiceConnection service, final ServiceErrorWriter errorWriter) throws NullPointerException{ @@ -141,7 +141,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { * by the user. Then it calls {@link #createQueryChecker(Collection)} with this list in order * to create a query checked. * </p> - * + * * <p><i>Note: * This function can not be overridded, but {@link #createQueryChecker(Collection)} can be. * </i></p> @@ -173,15 +173,15 @@ public abstract class AbstractTAPFactory extends TAPFactory { * <p>Create an object able to check the consistency between the ADQL query and the database. * That's to say, it checks whether the tables and columns used in the query really exist * in the database.</p> - * + * * <p><i>Note: * This implementation just create a {@link DBChecker} instance with the list given in parameter. * </i></p> - * + * * @param tables List of all available tables (and indirectly, columns). - * + * * @return A new ADQL query checker. - * + * * @throws TAPException If any error occurs while creating the query checker. */ protected QueryChecker createQueryChecker(final Collection<TAPTable> tables) throws TAPException{ @@ -198,7 +198,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation just create an {@link Uploader} instance with the given database connection.</p> - * + * * <p><i>Note: * This function should be overrided if you need to change the DB name of the TAP_UPLOAD schema. * Indeed, by overriding this function you can specify a given TAPSchema to use as TAP_UPLOAD schema @@ -217,7 +217,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation just create a {@link UWSService} instance.</p> - * + * * <p><i>Note: * This implementation is largely enough for a TAP service. It is not recommended to override * this function. @@ -238,7 +238,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation does not provided a backup manager. * It means that no asynchronous job will be restored and backuped.</p> - * + * * <p>You must override this function if you want enable the backup feature.</p> */ @Override @@ -248,7 +248,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation provides a basic {@link TAPJob} instance.</p> - * + * * <p> * If you need to add or modify the behavior of some functions of a {@link TAPJob}, * you must override this function and return your own extension of {@link TAPJob}. @@ -257,7 +257,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { @Override protected TAPJob createTAPJob(final HttpServletRequest request, final JobOwner owner) throws UWSException{ try{ - // Extract the HTTP request ID (the job ID should be the same, if not already used by another job): + // Extract the HTTP request ID (the job ID should be the same, if not already used by another job): String requestID = null; if (request.getAttribute(UWS.REQ_ATTRIBUTE_ID) != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) instanceof String) requestID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID).toString(); @@ -277,16 +277,17 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation provides a basic {@link TAPJob} instance.</p> - * + * * <p> - * If you need to add or modify the behavior of some functions of a {@link TAPJob}, - * you must override this function and return your own extension of {@link TAPJob}. + * If you need to add or modify the behavior of some functions of a + * {@link TAPJob}, you must override this function and return your own + * extension of {@link TAPJob}. * </p> */ @Override - protected TAPJob createTAPJob(final String jobId, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{ + protected TAPJob createTAPJob(final String jobId, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{ try{ - return new TAPJob(jobId, owner, params, quote, startTime, endTime, results, error); + return new TAPJob(jobId, creationTime, owner, params, quote, startTime, endTime, results, error); }catch(TAPException te){ if (te.getCause() != null && te.getCause() instanceof UWSException) throw (UWSException)te.getCause(); @@ -297,7 +298,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation extracts standard TAP parameters from the given request.</p> - * + * * <p> * Non-standard TAP parameters are added in a map inside the returned {@link TAPParameters} object * and are accessible with {@link TAPParameters#get(String)} and {@link TAPParameters#getAdditionalParameters()}. @@ -312,7 +313,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { /** * <p>This implementation extracts standard TAP parameters from the given request.</p> - * + * * <p> * Non-standard TAP parameters are added in a map inside the returned {@link TAPParameters} object * and are accessible with {@link TAPParameters#get(String)} and {@link TAPParameters#getAdditionalParameters()}. diff --git a/src/tap/TAPFactory.java b/src/tap/TAPFactory.java index f4f6b7a46a43753e8d3093437b02ef6490d7f351..d7974ab3a6bf2b9d6e28be697085db8d449ce102 100644 --- a/src/tap/TAPFactory.java +++ b/src/tap/TAPFactory.java @@ -2,21 +2,21 @@ package tap; /* * This file is part of TAPLibrary. - * + * * TAPLibrary 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. - * + * * TAPLibrary 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 TAPLibrary. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -25,6 +25,10 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import adql.parser.ADQLParser; +import adql.parser.ADQLQueryFactory; +import adql.parser.QueryChecker; +import adql.query.ADQLQuery; import tap.db.DBConnection; import tap.metadata.TAPSchema; import tap.parameters.TAPParameters; @@ -42,14 +46,10 @@ import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; import uws.service.file.UWSFileManager; import uws.service.request.RequestParser; -import adql.parser.ADQLParser; -import adql.parser.ADQLQueryFactory; -import adql.parser.QueryChecker; -import adql.query.ADQLQuery; /** * <p>Let build essential objects of the TAP service.</p> - * + * * <p>Basically, it means answering to the following questions:</p> * <ul> * <li>how to connect to the database? <i>({@link DBConnection})</i></li> @@ -61,9 +61,9 @@ import adql.query.ADQLQuery; * <li>how to parser an ADQL query? <i>({@link ADQLParser})</i></li> * <li>how to check ADQL queries? <i>({@link QueryChecker})</i></li> * </ul> - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (04/2015) + * @version 2.2 (09/2017) */ public abstract class TAPFactory implements UWSFactory { @@ -73,9 +73,9 @@ public abstract class TAPFactory implements UWSFactory { /** * Build a basic {@link TAPFactory}. * Nothing is done except setting the service connection. - * + * * @param service Configuration of the TAP service. <i>MUST NOT be NULL</i> - * + * * @throws NullPointerException If the given {@link ServiceConnection} is NULL. */ protected TAPFactory(final ServiceConnection service) throws NullPointerException{ @@ -87,11 +87,11 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Get the object to use when an error must be formatted and written to the user.</p> - * + * * <p>This formatted error will be either written in an HTTP response or in a job error summary.</p> - * + * * @return The error writer to use. - * + * * @since 2.0 */ public abstract ServiceErrorWriter getErrorWriter(); @@ -102,63 +102,63 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Get a free database connection.</p> - * + * * <p> * <i>Free</i> means this connection is not currently in use and will be exclusively dedicated to the function/process/thread * which has asked for it by calling this function. * </p> - * + * * <p><i>Note: * This function can create on the fly a new connection OR get a free one from a connection pool. Considering the * creation time of a database connection, the second way is recommended. * </i></p> - * + * * <p><b>IMPORTANT:</b> * The returned connection MUST be freed after having used it. * </p> - * + * * <p><i><b>WARNING:</b> * Some implementation may free the connection automatically when not used for a specific time. * So, do not forget to free the connection after use! * </i></p> - * + * * @param jobID ID of the job/thread/process which has asked for this connection. <i>note: The returned connection must then be identified thanks to this ID.</i> - * + * * @return A new and free connection to the database. <b>MUST BE NOT NULL, or otherwise a TAPException should be returned.</b> - * + * * @throws TAPException If there is any error while getting a free connection. - * + * * @since 2.0 */ public abstract DBConnection getConnection(final String jobID) throws TAPException; /** * <p>Free the given connection.</p> - * + * * <p> * This function is called by the TAP library when a job/thread does not need this connection any more. It aims * to free resources associated to the given database connection. * </p> - * + * * <p><i>Note: * This function can just close definitely the connection OR give it back to a connection pool. The implementation is * here totally free! * </i></p> - * + * * @param conn The connection to close. - * + * * @since 2.0 */ public abstract void freeConnection(final DBConnection conn); /** * <p>Destroy all resources (and particularly DB connections and JDBC driver) allocated in this factory.</p> - * + * * <p><i>Note: * This function is called when the TAP service is shutting down. * After this call, the factory may not be able to provide any closed resources ; its behavior may be unpredictable. * </i></p> - * + * * @since 2.0 */ public abstract void destroy(); @@ -169,20 +169,20 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Create the object able to execute an ADQL query and to write and to format its result.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory} * </i></p> - * + * * @return An ADQL executor. - * + * * @throws TAPException If any error occurs while creating an ADQL executor. */ public abstract ADQLExecutor createADQLExecutor() throws TAPException; /** * <p>Create a parser of ADQL query.</p> - * + * * <p><i>Warning: * This parser can be created with a query factory and/or a query checker. * {@link #createQueryFactory()} will be used only if the default query factory (or none) is set @@ -190,33 +190,33 @@ public abstract class TAPFactory implements UWSFactory { * Idem for {@link #createQueryChecker(TAPSchema)}: it will used only if no query checker is set * in the returned ADQL parser. * </i></p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @return An ADQL query parser. - * + * * @throws TAPException If any error occurs while creating an ADQL parser. - * + * * @since 2.0 */ public abstract ADQLParser createADQLParser() throws TAPException; /** * <p>Create a factory able to build every part of an {@link ADQLQuery} object.</p> - * + * * <p><i>Warning: * This function is used only if the default query factory (or none) is set in the ADQL parser * returned by {@link #createADQLParser()}. * </i></p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory} - * </i></p> - * + * </i></p> + * * @return An {@link ADQLQuery} factory. - * + * * @throws TAPException If any error occurs while creating the factory. */ public abstract ADQLQueryFactory createQueryFactory() throws TAPException; @@ -225,20 +225,20 @@ public abstract class TAPFactory implements UWSFactory { * <p>Create an object able to check the consistency between the ADQL query and the database. * That's to say, it checks whether the tables and columns used in the query really exist * in the database.</p> - * + * * <p><i>Warning: * This function is used only if no query checker is set in the ADQL parser * returned by {@link #createADQLParser()}. * </i></p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory} * </i></p> - * + * * @param uploadSchema ADQL schema containing the description of all uploaded tables. - * + * * @return A query checker. - * + * * @throws TAPException If any error occurs while creating a query checker. */ public abstract QueryChecker createQueryChecker(final TAPSchema uploadSchema) throws TAPException; @@ -249,15 +249,15 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Create an object able to manage the creation of submitted user tables (in VOTable) into the database.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @param dbConn The database connection which has requested an {@link Uploader}. - * + * * @return An {@link Uploader}. - * + * * @throws TAPException If any error occurs while creating an {@link Uploader} instance. */ public abstract Uploader createUploader(final DBConnection dbConn) throws TAPException; @@ -269,44 +269,44 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Create the object which will manage the asynchronous resource of the TAP service. * This resource is a UWS service.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @return A UWS service which will be the asynchronous resource of this TAP service. - * + * * @throws TAPException If any error occurs while creating this UWS service. */ public abstract UWSService createUWS() throws TAPException; /** * <p>Create the object which will manage the backup and restoration of all asynchronous jobs.</p> - * + * * <p><i>Note: * This function may return NULL. If it does, asynchronous jobs won't be backuped. * </i></p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @param uws The UWS service which has to be backuped and restored. - * + * * @return The backup manager to use. <i>MAY be NULL</i> - * + * * @throws TAPException If any error occurs while creating this backup manager. */ public abstract UWSBackupManager createUWSBackupManager(final UWSService uws) throws TAPException; /** * <p>Creates a (PENDING) UWS job from the given HTTP request.</p> - * + * * <p> * This implementation just call {@link #createTAPJob(HttpServletRequest, JobOwner)} * with the given request, in order to ensure that the returned object is always a {@link TAPJob}. * </p> - * + * * @see uws.service.AbstractUWSFactory#createJob(javax.servlet.http.HttpServletRequest, uws.job.user.JobOwner) * @see #createTAPJob(HttpServletRequest, JobOwner) */ @@ -317,52 +317,57 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Create a PENDING asynchronous job from the given HTTP request.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @param request Request which contains all parameters needed to set correctly the asynchronous job to create. * @param owner The user which has requested the job creation. - * + * * @return A new PENDING asynchronous job. - * + * * @throws UWSException If any error occurs while reading the parameters in the request or while creating the job. */ protected abstract TAPJob createTAPJob(final HttpServletRequest request, final JobOwner owner) throws UWSException; /** * <p>Creates a UWS job with the following attributes.</p> - * + * * <p> - * This implementation just call {@link #createTAPJob(String, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)} - * with the given parameters, in order to ensure that the returned object is always a {@link TAPJob}. + * This implementation just call {@link #createTAPJob(String, long, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)} + * with the given parameters, in order to ensure that the returned object + * is always a {@link TAPJob}. * </p> * * <p><i>Note 1: - * This function is mainly used to restore a UWS job at the UWS initialization. + * This function is mainly used to restore a UWS job at the UWS + * initialization. * </i></p> - * + * * <p><i>Note 2: - * The job phase is chosen automatically from the given job attributes (i.e. no endTime => PENDING, no result and no error => ABORTED, ...). + * The job phase is chosen automatically from the given job attributes + * (i.e. no endTime => PENDING, no result and no error => ABORTED, ...). * </i></p> - * - * @see uws.service.AbstractUWSFactory#createJob(java.lang.String, uws.job.user.JobOwner, uws.job.parameters.UWSParameters, long, long, long, java.util.List, uws.job.ErrorSummary) - * @see #createTAPJob(String, JobOwner, TAPParameters, long, long, long, List, ErrorSummary) + * + * @see uws.service.AbstractUWSFactory#createJob(String, long, JobOwner, UWSParameters, long, long, long, List, ErrorSummary) + * @see #createTAPJob(String, long, JobOwner, TAPParameters, long, long, long, List, ErrorSummary) */ @Override - public final UWSJob createJob(String jobId, JobOwner owner, final UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{ - return createTAPJob(jobId, owner, (TAPParameters)params, quote, startTime, endTime, results, error); + public final UWSJob createJob(String jobId, long creationTime, JobOwner owner, final UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{ + return createTAPJob(jobId, creationTime, owner, (TAPParameters)params, quote, startTime, endTime, results, error); } /** * <p>Create a PENDING asynchronous job with the given parameters.</p> - * + * * <p><i>Note: * A default implementation is provided in {@link AbstractTAPFactory}. * </i></p> - * + * * @param jobId ID of the job (NOT NULL). + * @param creationTime Creation date/time of the job (SHOULD NOT BE + * NEGATIVE OR NULL). * @param owner Owner of the job. * @param params List of all input job parameters. * @param quote Its quote (in seconds). @@ -370,21 +375,23 @@ public abstract class TAPFactory implements UWSFactory { * @param endTime Date/Time of the end of this job. * @param results All results of this job. * @param error The error which ended the job to create. - * + * * @return A new PENDING asynchronous job. - * + * * @throws UWSException If there is an error while creating the job. + * + * @since 2.2 */ - protected abstract TAPJob createTAPJob(final String jobId, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException; + protected abstract TAPJob createTAPJob(final String jobId, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException; /** * <p>Create the thread which will execute the task described by the given UWSJob instance.</p> - * + * * <p> * This function is definitely implemented here and can not be overridden. The processing of * an ADQL query must always be the same in a TAP service ; it is completely done by {@link AsyncThread}. * </p> - * + * * @see uws.service.UWSFactory#createJobThread(uws.job.UWSJob) * @see AsyncThread */ @@ -402,13 +409,13 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Extract the parameters from the given request (multipart or not).</p> - * + * * <p> * This function is used only to create the set of parameters for a TAP job (synchronous or asynchronous). * Thus, it just call {@link #createTAPParameters(HttpServletRequest)} with the given request, in order to ensure * that the returned object is always a {@link TAPParameters}. * </p> - * + * * @see #createTAPParameters(HttpServletRequest) */ @Override @@ -425,27 +432,27 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Extract all the TAP parameters from the given HTTP request (multipart or not) and return them.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @param request The HTTP request containing the TAP parameters to extract. - * + * * @return An object gathering all successfully extracted TAP parameters. - * - * @throws TAPException If any error occurs while extracting the parameters. + * + * @throws TAPException If any error occurs while extracting the parameters. */ public abstract TAPParameters createTAPParameters(final HttpServletRequest request) throws TAPException; /** * <p>Identify and gather all identified parameters of the given map inside a {@link TAPParameters} object.</p> - * + * * <p> * This implementation just call {@link #createTAPParameters(Map)} with the given map, in order to ensure * that the returned object is always a {@link TAPParameters}. * </p> - * + * * @see uws.service.AbstractUWSFactory#createUWSParameters(java.util.Map) * @see #createTAPParameters(Map) */ @@ -463,13 +470,13 @@ public abstract class TAPFactory implements UWSFactory { /** * <p>Identify all TAP parameters and gather them inside a {@link TAPParameters} object.</p> - * + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory}. * </i></p> - * + * * @param params Map containing all parameters. - * + * * @return An object gathering all successfully identified TAP parameters. * * @throws TAPException If any error occurs while creating the {@link TAPParameters} object. diff --git a/src/tap/TAPJob.java b/src/tap/TAPJob.java index 7640e83856f24c46e9a640d357d0a14bf0fd35f7..5c4a405e2380e29e4616e2b369485ff4fa974422 100644 --- a/src/tap/TAPJob.java +++ b/src/tap/TAPJob.java @@ -2,21 +2,21 @@ package tap; /* * This file is part of TAPLibrary. - * + * * TAPLibrary 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. - * + * * TAPLibrary 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 TAPLibrary. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -37,15 +37,18 @@ import uws.job.user.JobOwner; import uws.service.log.UWSLog.LogLevel; /** - * <p>Description of a TAP job. This class is used for asynchronous but also synchronous queries.</p> - * + * Description of a TAP job. This class is used for asynchronous but also + * synchronous queries. + * * <p> - * On the contrary to {@link UWSJob}, it is loading parameters from {@link TAPParameters} instances rather than {@link UWSParameters}. - * However, {@link TAPParameters} is an extension of {@link UWSParameters}. That's what allow the UWS library to use both {@link TAPJob} and {@link TAPParameters}. + * On the contrary to {@link UWSJob}, it is loading parameters from + * {@link TAPParameters} instances rather than {@link UWSParameters}. However, + * {@link TAPParameters} is an extension of {@link UWSParameters}. That's what + * allow the UWS library to use both {@link TAPJob} and {@link TAPParameters}. * </p> - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 2.1 (01/2016) + * @version 2.2 (09/2017) */ public class TAPJob extends UWSJob { private static final long serialVersionUID = 1L; @@ -96,13 +99,13 @@ public class TAPJob extends UWSJob { /** * <p>Build a pending TAP job with the given parameters.</p> - * + * * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN} * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p> - * + * * @param owner User who owns this job. <i>MAY BE NULL</i> * @param tapParams Set of parameters. - * + * * @throws TAPException If one of the given parameters has a forbidden or wrong value. */ public TAPJob(final JobOwner owner, final TAPParameters tapParams) throws TAPException{ @@ -114,17 +117,17 @@ public class TAPJob extends UWSJob { /** * <p>Build a pending TAP job with the given parameters. * The given HTTP request ID will be used as Job ID if not already used by another job.</p> - * + * * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN} * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p> - * + * * @param owner User who owns this job. <i>MAY BE NULL</i> * @param tapParams Set of parameters. * @param requestID ID of the HTTP request which has initiated the creation of this job. * <i>Note: if NULL, empty or already used, a job ID will be generated thanks to {@link #generateJobId()}.</i> - * + * * @throws TAPException If one of the given parameters has a forbidden or wrong value. - * + * * @since 2.1 */ public TAPJob(final JobOwner owner, final TAPParameters tapParams, final String requestID) throws TAPException{ @@ -134,29 +137,40 @@ public class TAPJob extends UWSJob { } /** - * <p>Restore a job in a state defined by the given parameters. - * The phase must be set separately with {@link #setPhase(uws.job.ExecutionPhase, boolean)}, where the second parameter is true.</p> - * - * @param jobID ID of the job. - * @param owner User who owns this job. - * @param params Set of not-standard UWS parameters (i.e. what is called by {@link UWSJob} as additional parameters ; they includes all TAP parameters). - * @param quote Quote of this job. - * @param startTime Date/Time at which this job started. <i>(if not null, it means the job execution was finished, so a endTime should be provided)</i> - * @param endTime Date/Time at which this job finished. - * @param results List of results. <i>NULL if the job has not been executed, has been aborted or finished with an error.</i> - * @param error Error with which this job ends. - * - * @throws TAPException If one of the given parameters has a forbidden or wrong value. + * Restore a job in a state defined by the given parameters. + * The phase must be set separately with {@link #setPhase(uws.job.ExecutionPhase, boolean)}, + * where the second parameter is true. + * + * @param jobID ID of the job. + * @param creationTime Creation date/time of the job (SHOULD NOT BE NEGATIVE OR NULL). + * @param owner User who owns this job. + * @param params Set of not-standard UWS parameters (i.e. what is + * called by {@link UWSJob} as additional parameters ; + * they includes all TAP parameters). + * @param quote Quote of this job. + * @param startTime Date/Time at which this job started. + * <i>(if not null, it means the job execution was + * finished, so a endTime should be provided)</i> + * @param endTime Date/Time at which this job finished. + * @param results List of results. + * <i>NULL if the job has not been executed, has been + * aborted or finished with an error.</i> + * @param error Error with which this job ends. + * + * @throws TAPException If one of the given parameters has a forbidden or + * wrong value. + * + * @since 2.2 */ - public TAPJob(final String jobID, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws TAPException{ - super(jobID, owner, params, quote, startTime, endTime, results, error); + public TAPJob(final String jobID, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws TAPException{ + super(jobID, creationTime, owner, params, quote, startTime, endTime, results, error); this.tapParams = params; this.tapParams.check(); } /** * Get the object storing and managing the set of all (UWS and TAP) parameters. - * + * * @return The object managing all job parameters. */ public final TAPParameters getTapParams(){ @@ -165,9 +179,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the value of the REQUEST parameter.</p> - * + * * <p>This value must be {@value #REQUEST_DO_QUERY}.</p> - * + * * @return REQUEST value. */ public final String getRequest(){ @@ -176,7 +190,7 @@ public class TAPJob extends UWSJob { /** * Get the value of the FORMAT parameter. - * + * * @return FORMAT value. */ public final String getFormat(){ @@ -185,9 +199,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the value of the LANG parameter.</p> - * + * * <p>This value should always be {@value #LANG_ADQL} in this version of the library</p> - * + * * @return LANG value. */ public final String getLanguage(){ @@ -196,9 +210,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the value of the MAXREC parameter.</p> - * + * * <p>If this value is negative, it means the number of output rows is not limited.</p> - * + * * @return MAXREC value. */ public final int getMaxRec(){ @@ -207,7 +221,7 @@ public class TAPJob extends UWSJob { /** * Get the value of the QUERY parameter (i.e. the query, in the language returned by {@link #getLanguage()}, to execute). - * + * * @return QUERY value. */ public final String getQuery(){ @@ -216,9 +230,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the value of the VERSION parameter.</p> - * + * * <p>This value should be {@value #VERSION_1_0} in this version of the library.</p> - * + * * @return VERSION value. */ public final String getVersion(){ @@ -227,9 +241,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the value of the UPLOAD parameter.</p> - * + * * <p>This value must be formatted as specified by the TAP standard (= a semicolon separated list of DALI uploads).</p> - * + * * @return UPLOAD value. */ public final String getUpload(){ @@ -238,9 +252,9 @@ public class TAPJob extends UWSJob { /** * <p>Get the list of tables to upload in the database for the query execution.</p> - * + * * <p>The returned array is an interpretation of the UPLOAD parameter.</p> - * + * * @return List of tables to upload. */ public final DALIUpload[] getTablesToUpload(){ @@ -249,13 +263,13 @@ public class TAPJob extends UWSJob { /** * <p>Get the execution report.</p> - * + * * <p> * This report is available only during or after the job execution. * It tells in which step the execution is, and how long was the previous steps. * It can also give more information about the number of resulting rows and columns. * </p> - * + * * @return The execReport. */ public final TAPExecutionReport getExecReport(){ @@ -264,14 +278,14 @@ public class TAPJob extends UWSJob { /** * <p>Set the execution report.</p> - * + * * <p><b>IMPORTANT: * This function can be called only if the job is running or is being restored, otherwise an exception would be thrown. * It should not be used by implementors, but only by the internal library processing. * </b></p> - * + * * @param execReport An execution report. - * + * * @throws UWSException If this job has never been restored and is not running. */ public final void setExecReport(final TAPExecutionReport execReport) throws UWSException{ @@ -282,14 +296,14 @@ public class TAPJob extends UWSJob { /** * <p>Create the thread to use for the execution of this job.</p> - * + * * <p><i>Note: If the job already exists, this function does nothing.</i></p> - * + * * @throws NullPointerException If the factory returned NULL rather than the asked {@link JobThread}. * @throws UWSException If the thread creation fails. - * + * * @see TAPFactory#createJobThread(UWSJob) - * + * * @since 2.0 */ private final void createThread() throws NullPointerException, UWSException{ @@ -302,18 +316,18 @@ public class TAPJob extends UWSJob { /** * <p>Check whether this job is able to start right now.</p> - * + * * <p> * Basically, this function try to get a database connection. If none is available, * then this job can not start and this function return FALSE. In all the other cases, * TRUE is returned. * </p> - * + * * <p><b>Warning:</b> This function will indirectly open and keep a database connection, so that the job can be started just after its call. * If it turns out that the execution won't start just after this call, the DB connection should be closed in some way in order to save database resources.</i></p> - * + * * @return <i>true</i> if this job can start right now, <i>false</i> otherwise. - * + * * @since 2.0 */ public final boolean isReadyForExecution(){ @@ -390,7 +404,7 @@ public class TAPJob extends UWSJob { /** * This exception is thrown by a job execution when no database connection are available anymore. - * + * * @author Grégory Mantelet (ARI) * @version 2.0 (02/2015) * @since 2.0 diff --git a/src/uws/config/ConfigurableUWSFactory.java b/src/uws/config/ConfigurableUWSFactory.java index 19bbb156e3654234aff23b2f61f542b9a1cc1f74..dc685679013d78c2cf455c37e11d9d6936d8fb57 100644 --- a/src/uws/config/ConfigurableUWSFactory.java +++ b/src/uws/config/ConfigurableUWSFactory.java @@ -2,20 +2,20 @@ 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-2017 - Astronomisches Rechen Institut (ARI) */ @@ -67,9 +67,9 @@ 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 (06/2017) + * @version 4.3 (09/2017) * @since 4.2 */ public class ConfigurableUWSFactory implements UWSFactory { @@ -85,7 +85,7 @@ public class ConfigurableUWSFactory implements UWSFactory { 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. @@ -96,7 +96,7 @@ public class ConfigurableUWSFactory implements UWSFactory { /** * 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> @@ -107,9 +107,9 @@ public class ConfigurableUWSFactory implements UWSFactory { * <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{ @@ -296,7 +296,7 @@ public class ConfigurableUWSFactory implements UWSFactory { /** * 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> @@ -369,20 +369,20 @@ public class ConfigurableUWSFactory implements UWSFactory { /** * 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{ @@ -632,8 +632,8 @@ public class ConfigurableUWSFactory implements UWSFactory { } @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); + public UWSJob createJob(String jobID, long creationTime, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{ + return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error); } @Override diff --git a/src/uws/job/UWSJob.java b/src/uws/job/UWSJob.java index 9c6dae4a82a65634540208c7518ea0b6c5d19e89..35b45af8482721f533d094967f5983abcd7b16d2 100644 --- a/src/uws/job/UWSJob.java +++ b/src/uws/job/UWSJob.java @@ -115,7 +115,7 @@ import uws.service.request.UploadFile; * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.2 (09/2017) + * @version 4.3 (09/2017) */ public class UWSJob extends SerializableUWSObject { private static final long serialVersionUID = 1L; @@ -132,6 +132,10 @@ public class UWSJob extends SerializableUWSObject { /** Name of the parameter <i>jobId</i>. */ public static final String PARAM_JOB_ID = "jobId"; + /** Name of the parameter <i>creationTime</i>. + * @since 4.3 */ + public static final String PARAM_CREATION_TIME = "creationTime"; + /** Name of the parameter <i>runId</i>. */ public static final String PARAM_RUN_ID = "runId"; @@ -201,6 +205,13 @@ public class UWSJob extends SerializableUWSObject { * To change the way this ID is generated or its format you must override this function.</i> */ protected final String jobId; + /** Date of the initial creation of this job.<BR /> + * <i><u>Note:</u> This attribute can be set only automatically at creation + * by the UWS service and can not be set or changed by a user (even its + * owner).</i> + * @since 4.3 */ + protected final Date creationTime; + /** The identifier of the creator of this job.<BR /> * <i><u>Note:</u> This object will not exist for all invocations of the UWS conformant protocol, * but only in cases where the access to the service is authenticated.</i> */ @@ -288,10 +299,15 @@ public class UWSJob extends SerializableUWSObject { } /** - * <p>Builds a job of the given owner and from a map of all parameters (UWS and additional parameters).</p> + * Builds a job of the given owner and from a map of all parameters (UWS + * and additional parameters). * - * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN} - * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p> + * <p><i><u>Note:</u> + * if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the + * value {@link #PHASE_RUN} the job execution starts immediately after the + * job has been added to a job list or after + * {@link #applyPhaseParam(JobOwner)} is called. + * </i></p> * * @param owner Job.owner ({@link #PARAM_OWNER}). * @param params UWS standard and non-standard parameters. @@ -299,6 +315,8 @@ public class UWSJob extends SerializableUWSObject { * @see UWSParameters#init() */ public UWSJob(JobOwner owner, final UWSParameters params){ + this.creationTime = new Date(); + this.owner = owner; phase = new JobPhase(this); @@ -337,6 +355,8 @@ public class UWSJob extends SerializableUWSObject { * @since 4.2 */ public UWSJob(JobOwner owner, final UWSParameters params, final String requestID){ + this.creationTime = new Date(); + this.owner = owner; phase = new JobPhase(this); @@ -371,12 +391,15 @@ public class UWSJob extends SerializableUWSObject { * * <p>Builds a job of the given owner with all the given parameter.</p> * - * <p><i> - * <u>Note:</u> The job phase is automatically set in function of the last parameters (startTime, endTime, results and error). - * Only the following execution phase are possible: PENDING, ABORTED, ERROR and COMPLETED. + * <p><i><u>Note:</u> + * The job phase is automatically set in function of the last parameters + * (startTime, endTime, results and error). Only the following execution + * phase are possible: PENDING, ABORTED, ERROR and COMPLETED. * </i></p> * * @param jobID The ID of this job (NOT NULL). + * @param creationTime Its creation date/time (SHOULD NOT BE NEGATIVE OR + * NULL). * @param owner Its owner. * @param params UWS standard and non-standard parameters. * @param quote Its quote (in seconds). @@ -386,11 +409,22 @@ public class UWSJob extends SerializableUWSObject { * @param error Its error (if phase=ERROR). * * @throws NullPointerException If the given ID is NULL. + * + * @since 4.3 */ - public UWSJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws NullPointerException{ + public UWSJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws NullPointerException{ if (jobID == null) throw new NullPointerException("Missing job ID => impossible to build a Job without a valid ID!"); + this.creationTime = (creationTime <= 0) ? new Date() : new Date(creationTime); + /* Note: + * If no creation date is provided, it may be because we are getting + * the data from an old backup file (so, created by a UWS service + * previously implementing UWS-1.0). Except this missing information, + * the rest of the job properties may be ok, so there is no need to + * throw an error for an accessory property like the creation time. + * So, the current date is set instead. */ + this.jobId = jobID; this.owner = owner; @@ -462,11 +496,15 @@ public class UWSJob extends SerializableUWSObject { /** * <p>Gets the value of the specified parameter.</p> * - * <p><i><u>note:</u> No case sensitivity for the UWS parameters ON THE CONTRARY TO the names of the additional parameters (which are case sensitive).</i></p> + * <p><i><u>note:</u> + * No case sensitivity for the UWS parameters ON THE CONTRARY TO the names + * of the additional parameters (which are case sensitive). + * </i></p> * * @param name Name of the parameter to get. * - * @return Its value or <i>null</i> if there is no parameter with the given name or if the value is <i>null</i>. + * @return Its value or <i>null</i> if there is no parameter with the given + * name or if the value is <i>null</i>. * * @see UWSParameters#get(String) */ @@ -477,6 +515,8 @@ public class UWSJob extends SerializableUWSObject { name = name.trim(); if (name.equalsIgnoreCase(PARAM_JOB_ID)) return jobId; + else if (name.equalsIgnoreCase(PARAM_CREATION_TIME)) + return creationTime; else if (name.equalsIgnoreCase(PARAM_OWNER)) return owner; else if (name.equalsIgnoreCase(PARAM_PHASE)) @@ -1002,6 +1042,17 @@ public class UWSJob extends SerializableUWSObject { return addOrUpdateParameters(params, null); } + /** + * Gets the creation date/time of this job. + * + * @return The job creation date/time. + * + * @since 4.3 + */ + public final Date getCreationTime(){ + return creationTime; + } + /** * <p>Adds or updates the given parameters ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p> * diff --git a/src/uws/job/serializer/JSONSerializer.java b/src/uws/job/serializer/JSONSerializer.java index 48dc5dbf5b28df33c7df44ade4199d3863ff6880..7a5089ac7c74f0b81799bf9e54636c936d362b4a 100644 --- a/src/uws/job/serializer/JSONSerializer.java +++ b/src/uws/job/serializer/JSONSerializer.java @@ -2,21 +2,21 @@ package uws.job.serializer; /* * 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 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -34,10 +34,10 @@ import uws.service.UWSUrl; /** * Lets serializing any UWS resource in JSON. - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (09/2014) - * + * @version 4.3 (09/2017) + * * @see Json4Uws */ public class JSONSerializer extends UWSSerializer { @@ -96,6 +96,11 @@ public class JSONSerializer extends UWSSerializer { return Json4Uws.getJson(UWSJob.PARAM_QUOTE, job.getQuote()).toString(); } + @Override + public String getCreationTime(final UWSJob job, final boolean root) throws JSONException{ + return Json4Uws.getJson(UWSJob.PARAM_CREATION_TIME, ISO8601Format.format(job.getCreationTime())).toString(); + } + @Override public String getExecutionDuration(final UWSJob job, final boolean root) throws JSONException{ return Json4Uws.getJson(UWSJob.PARAM_EXECUTION_DURATION, job.getExecutionDuration()).toString(); diff --git a/src/uws/job/serializer/UWSSerializer.java b/src/uws/job/serializer/UWSSerializer.java index 6a191d7e598f3cdfac7c370f21e03d8b7eae1da9..64f0a7307105c7b89e7c446c5c7e44608d949772 100644 --- a/src/uws/job/serializer/UWSSerializer.java +++ b/src/uws/job/serializer/UWSSerializer.java @@ -2,21 +2,21 @@ package uws.job.serializer; /* * 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 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -39,10 +39,10 @@ import uws.service.UWSUrl; * <li>XML by the class {@link XMLSerializer}</li> * <li>JSON by the class {@link JSONSerializer}</li> * </ul> - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (12/2014) - * + * @version 4.3 (09/2017) + * * @see XMLSerializer * @see JSONSerializer */ @@ -61,15 +61,15 @@ public abstract class UWSSerializer implements Serializable { /** * Serializes the given parameter of the given job * or serializes the whole job if the given attributes array is empty or <i>null</i>. - * + * * @param job The job whose the attribute must be serialized. * @param attributes All the given attributes (may be <i>null</i> or empty). * @param root <i>false</i> if the attribute to serialize will be included * in a top level serialization (for a job attribute: job), <i>true</i> otherwise. - * + * * @return The serialization of the given attribute * or the serialization of the whole job if the given attributes array is empty or <i>null</i>. - * + * * @throws Exception If an error occurs while serializing the specified job/attribute/parameter/result. */ public String getJob(final UWSJob job, final String[] attributes, final boolean root) throws Exception{ @@ -93,6 +93,9 @@ public abstract class UWSSerializer implements Serializable { // QUOTE: else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_QUOTE)) return job.getQuote() + ""; + // CREATION TIME: + else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_CREATION_TIME)) + return ISO8601Format.format(job.getCreationTime()); // START TIME: else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_START_TIME)) return (job.getStartTime() == null) ? "" : ISO8601Format.format(job.getStartTime()); @@ -162,20 +165,20 @@ public abstract class UWSSerializer implements Serializable { /** * Gets the MIME type of the serialization format used by this serializer. - * + * * @return The corresponding MIME type. */ public abstract String getMimeType(); /** * Serializes the given UWS. - * + * * @param uws The UWS to serialize. - * + * * @return The serialization of the given UWS. - * + * * @throws Exception If there is an error during the serialization. - * + * * @see UWSSerializer#getUWS(UWS, JobOwner) */ public String getUWS(final UWS uws) throws Exception{ @@ -184,25 +187,25 @@ public abstract class UWSSerializer implements Serializable { /** * Serializes the given UWS for the specified user. - * + * * @param uws The UWS to serialize. * @param user The user which has asked the serialization of the given UWS. - * + * * @return The serialization of the UWS. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getUWS(final UWS uws, final JobOwner user) throws Exception; /** * Serializes the given jobs list. - * + * * @param jobsList The jobs list to serialize. * @param root <i>false</i> if the jobs list to serialize will be included * in a top level serialization (for a jobs list: uws), <i>true</i> otherwise. - * + * * @return The serialization of the given jobs list. - * + * * @throws Exception If there is an error during the serialization. */ public String getJobList(final JobList jobsList, final boolean root) throws Exception{ @@ -211,223 +214,239 @@ public abstract class UWSSerializer implements Serializable { /** * Serializes the given jobs list. - * + * * @param jobsList The jobs list to serialize. * @param owner The user which has asked the serialization of the given jobs list. * @param root <i>false</i> if the jobs list to serialize will be included * in a top level serialization (for a jobs list: uws), <i>true</i> otherwise. * @return The serialization of the given jobs list. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getJobList(final JobList jobsList, JobOwner owner, final boolean root) throws Exception; /** * Serializes the whole given job. - * + * * @param job The job to serialize. * @param root <i>false</i> if the job to serialize will be included * in a top level serialization (for a job: jobList), <i>true</i> otherwise. - * + * * @return The serialization of the given job. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getJob(final UWSJob job, final boolean root) throws Exception; /** * Serializes just a reference on the given job. - * + * * @param job The job to reference. * @param jobsListUrl URL to the jobs lists which contains the given job. - * + * * @return The serialization of a reference on the given job. - * + * * @throws Exception If there is an error during the serialization. - * + * * @since 3.1 */ public abstract String getJobRef(final UWSJob job, final UWSUrl jobsListUrl) throws Exception; /** * Serializes the ID of the given job. - * + * * @param job The job whose the ID must be serialized. * @param root <i>false</i> if the job ID to serialize will be included * in a top level serialization (for a job ID: job), <i>true</i> otherwise. - * + * * @return The serialization of the job ID. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getJobID(final UWSJob job, final boolean root) throws Exception; /** * Serializes the run ID of the given job. - * + * * @param job The job whose the run ID must be serialized. * @param root <i>false</i> if the run ID to serialize will be included * in a top level serialization (for a run ID: job), <i>true</i> otherwise. - * + * * @return The serialization of the run ID. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getRunID(final UWSJob job, final boolean root) throws Exception; /** * Serializes the owner ID of the given job. - * + * * @param job The job whose the owner ID must be serialized. * @param root <i>false</i> if the owner ID to serialize will be included * in a top level serialization (for a owner ID: job), <i>true</i> otherwise. - * + * * @return The serialization of the owner ID. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getOwnerID(final UWSJob job, final boolean root) throws Exception; /** * Serializes the phase of the given job. - * + * * @param job The job whose the phase must be serialized. * @param root <i>false</i> if the phase to serialize will be included * in a top level serialization (for a phase: job), <i>true</i> otherwise. - * + * * @return The serialization of the phase. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getPhase(final UWSJob job, final boolean root) throws Exception; /** * Serializes the quote of the given job. - * + * * @param job The job whose the quote must be serialized. * @param root <i>false</i> if the quote to serialize will be included * in a top level serialization (for a quote: job), <i>true</i> otherwise. - * + * * @return The serialization of the quote. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getQuote(final UWSJob job, final boolean root) throws Exception; + /** + * Serializes the creation date/time of the given job. + * + * @param job The job whose the creation date/time must be serialized. + * @param root <i>false</i> if the creation time to serialize will be + * included in a top level serialization (for a creation time: + * job), <i>true</i> otherwise. + * + * @return The serialization of the job creation date/time. + * + * @throws Exception If there is an error during the serialization. + * + * @since 4.3 + */ + public abstract String getCreationTime(final UWSJob job, final boolean root) throws Exception; + /** * Serializes the start time of the given job. - * + * * @param job The job whose the start time must be serialized. * @param root <i>false</i> if the start time to serialize will be included * in a top level serialization (for a start time: job), <i>true</i> otherwise. - * + * * @return The serialization of the start time. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getStartTime(final UWSJob job, final boolean root) throws Exception; /** * Serializes the end time of the given job. - * + * * @param job The job whose the end time must be serialized. * @param root <i>false</i> if the end time to serialize will be included * in a top level serialization (for a end time: job), <i>true</i> otherwise. - * + * * @return The serialization of the end time. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getEndTime(final UWSJob job, final boolean root) throws Exception; /** * Serializes the execution duration of the given job. - * + * * @param job The job whose the execution duration must be serialized. * @param root <i>false</i> if the execution duration to serialize will be included * in a top level serialization (for a execution duration: job), <i>true</i> otherwise. - * + * * @return The serialization of the execution duration. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getExecutionDuration(final UWSJob job, final boolean root) throws Exception; /** * Serializes the destruction time of the given job. - * + * * @param job The job whose the destruction time must be serialized. * @param root <i>false</i> if the destruction time to serialize will be included * in a top level serialization (for a destruction time: job), <i>true</i> otherwise. - * + * * @return The serialization of the destruction time. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getDestructionTime(final UWSJob job, final boolean root) throws Exception; /** * Serializes the given error summary. - * + * * @param error The error to serialize. * @param root <i>false</i> if the error summary to serialize will be included * in a top level serialization (for an error summary: job), <i>true</i> otherwise. - * + * * @return The serialization of the error summary. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getErrorSummary(final ErrorSummary error, final boolean root) throws Exception; /** * Serializes the results of the given job. - * + * * @param job The job whose the results must be serialized. * @param root <i>false</i> if the results list to serialize will be included * in a top level serialization (for a list of results: job), <i>true</i> otherwise. - * + * * @return The serialization of the results. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getResults(final UWSJob job, final boolean root) throws Exception; /** * Serializes the given result. - * + * * @param result The result to serialize. * @param root <i>false</i> if the result to serialize will be included * in a top level serialization (for a result: results), <i>true</i> otherwise. - * + * * @return The serialization of the result. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getResult(final Result result, final boolean root) throws Exception; /** * Serializes the parameters of the given job. - * + * * @param job The job whose the parameters must be serialized. * @param root <i>false</i> if the parameters list to serialize will be included * in a top level serialization (for a list of parameters: job), <i>true</i> otherwise. - * + * * @return The serialization of the parameters. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getAdditionalParameters(final UWSJob job, final boolean root) throws Exception; /** * Serializes the specified parameter. - * + * * @param paramName The name of the parameter to serialize. * @param paramValue The value of the parameter to serialize. * @param root <i>false</i> if the parameter to serialize will be included * in a top level serialization (for a parameter: parameters), <i>true</i> otherwise. - * + * * @return The serialization of the parameter. - * + * * @throws Exception If there is an error during the serialization. */ public abstract String getAdditionalParameter(final String paramName, final Object paramValue, final boolean root) throws Exception; diff --git a/src/uws/job/serializer/XMLSerializer.java b/src/uws/job/serializer/XMLSerializer.java index b8a2e96f73762598edf79a7e54e866de98dfe5ae..44cb254e1ffed0700d271f7dc1eb7dfce9b47964 100644 --- a/src/uws/job/serializer/XMLSerializer.java +++ b/src/uws/job/serializer/XMLSerializer.java @@ -212,6 +212,7 @@ public class XMLSerializer extends UWSSerializer { xml.append(newLine).append(getOwnerID(job, false)); xml.append(newLine).append(getPhase(job, false)); xml.append(newLine).append(getQuote(job, false)); + xml.append(newLine).append(getCreationTime(job, false)); xml.append(newLine).append(getStartTime(job, false)); xml.append(newLine).append(getEndTime(job, false)); xml.append(newLine).append(getExecutionDuration(job, false)); @@ -247,18 +248,32 @@ public class XMLSerializer extends UWSSerializer { } StringBuffer xml = new StringBuffer("<jobref id=\""); + + // [MANDATORY] Set the job ID as an attribute: xml.append(escapeXMLAttribute(job.getJobId())).append('"'); - /* NOTE: NO ATTRIBUTE "runId" IN THE XML SCHEMA! - * if (job.getRunId() != null && job.getRunId().length() > 0) - * xml.append("\" runId=\"").append(escapeXMLAttribute(job.getRunId())); - */ - /* The XLink attributes are optional. So if no URL is available for this + /* [OPTIONAL] Set the XLink attributes. If no URL is available for this * Job reference, none is written here: */ if (url != null) xml.append(" xlink:type=\"simple\" xlink:href=\"").append(escapeXMLAttribute(url)).append('"'); - xml.append(">\n\t\t").append(getPhase(job, false)).append("\n\t</jobref>"); + xml.append('>'); + + // [MANDATORY] Append the execution phase: + xml.append("\n\t\t").append(getPhase(job, false)); + + // [OPTIONAL] Append the RUN ID (name/label of the job set by the user), if any: + if (job.getRunId() != null) + xml.append("\n\t\t").append(getRunID(job, false)); + + // [OPTIONAL] Append the job owner, if any: + if (job.getOwner() != null) + xml.append("\n\t\t").append(getOwnerID(job, false)); + + // [OPTIONAL] Append the creation time: + xml.append("\n\t\t").append(getCreationTime(job, false)); + + xml.append("\n\t</jobref>"); return xml.toString(); } @@ -306,6 +321,11 @@ public class XMLSerializer extends UWSSerializer { return xml.toString(); } + @Override + public String getCreationTime(final UWSJob job, final boolean root){ + return (new StringBuffer(root ? getHeader() : "")).append("<creationTime").append(getUWSNamespace(root)).append('>').append(ISO8601Format.format(job.getCreationTime())).append("</creationTime>").toString(); + } + @Override public String getStartTime(final UWSJob job, final boolean root){ StringBuffer xml = new StringBuffer(root ? getHeader() : ""); diff --git a/src/uws/service/AbstractUWSFactory.java b/src/uws/service/AbstractUWSFactory.java index 6acbe5770124fa1fc924a7c17c1d75bcdac2355e..389e35af04b6c688ae070ea9a99e6641cae9304a 100644 --- a/src/uws/service/AbstractUWSFactory.java +++ b/src/uws/service/AbstractUWSFactory.java @@ -2,20 +2,20 @@ package uws.service; /* * 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 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -45,11 +45,12 @@ import uws.service.request.RequestParser; import uws.service.request.UWSRequestParser; /** - * <p>Abstract implementation of {@link UWSFactory}. - * Only the function which creates a {@link JobThread} from a {@link UWSJob} needs to be implemented.</p> - * + * Abstract implementation of {@link UWSFactory}. + * Only the function which creates a {@link JobThread} from a {@link UWSJob} + * needs to be implemented. + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.2 (09/2017) + * @version 4.3 (09/2017) */ public abstract class AbstractUWSFactory implements UWSFactory { @@ -67,7 +68,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { * Builds a factory with a list of the name of all expected additional parameters. * These parameters will be identified by {@link UWSParameters} without taking into account their case * and they will stored with the case of their name in the given list. - * + * * @param expectedAdditionalParams Names of the expected parameters. */ public AbstractUWSFactory(final String[] expectedAdditionalParams){ @@ -102,8 +103,8 @@ public abstract class AbstractUWSFactory implements UWSFactory { } @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); + public UWSJob createJob(String jobID, long creationTime, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{ + return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error); } @Override @@ -124,7 +125,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Adds the name of an additional parameter which must be identified without taking into account its case * and then stored with the case of the given name. - * + * * @param paramName Name of an additional parameter. */ public final void addExpectedAdditionalParameter(final String paramName){ @@ -134,7 +135,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Gets the number of additional parameters which must be identified with no case sensitivity. - * + * * @return Number of expected additional parameters. */ public final int getNbExpectedAdditionalParameters(){ @@ -144,7 +145,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Gets the names of the expected additional parameters. These parameters are identified with no case sensitivity * and stored in the given case. - * + * * @return Names of the expected additional parameters. */ public final List<String> getExpectedAdditionalParameters(){ @@ -153,7 +154,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Gets an iterator on the names of the expected additional parameters. - * + * * @return An iterator on the names of the expected additional parameters. */ public final Iterator<String> expectedAdditionalParametersIterator(){ @@ -164,7 +165,7 @@ public abstract class AbstractUWSFactory implements UWSFactory { * Removes the name of an expected additional parameter. * This parameter will never be identify specifically and so, it will be stored in the same case as * in the initial Map or HttpServletRequest. - * + * * @param paramName Name of an additional parameter. */ public final void removeExpectedAdditionalParam(final String paramName){ @@ -199,10 +200,10 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Sets the controller of the specified input UWS job parameter. - * + * * @param paramName Name of the parameter with which the given controller will be associated. * @param controller An input parameter controller. - * + * * @return The former controller associated with the specified parameter * or <i>null</i> if there is no controller before this call * or if the given parameter name is <i>null</i> or an empty string. @@ -218,9 +219,9 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * Removes the controller of the specified input UWS job parameter. - * + * * @param paramName Name of the parameter whose the controller must be removed. - * + * * @return The removed controller * or <i>null</i> if there were no controller * or if the given name is <i>null</i> or an empty string. @@ -231,14 +232,14 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * <p>Lets configuring the execution duration default and maximum value.</p> - * + * * <p><i><u>note:</u> A new controller is created if needed. * Otherwise the current one (if it is an instance of {@link DestructionTimeController}) is updated.</i></p> - * + * * @param defaultDuration Default duration between the start and the end of the execution of a job. * @param maxDuration Maximum duration between the start and the end of the execution of a job that a user can set when creating/initializing a job. * @param allowModif <i>true</i> to allow the modification of this parameter after its initialization, <i>false</i> otherwise. - * + * * @see ExecutionDurationController */ public final void configureExecution(final long defaultDuration, final long maxDuration, final boolean allowModif){ @@ -258,16 +259,16 @@ public abstract class AbstractUWSFactory implements UWSFactory { /** * <p>Lets configuring the destruction time default and maximum value.</p> - * + * * <p><i><u>note:</u> A new controller is created if needed. * Otherwise the current one (if it is an instance of {@link ExecutionDurationController}) is updated.</i></p> - * + * * @param defaultTime Default time since the job creation and its destruction. * @param defaultTimeUnit Unit of the default time (i.e. minutes, days, ...). * @param maxTime Maximum time since the job creation and its destruction that a user can set when creating/initializing a job. * @param maxTimeUnit Unit of the maximum time (i.e. minutes, days, ...). * @param allowModif <i>true</i> to allow the modification of this parameter after its initialization, <i>false</i> otherwise. - * + * * @see DestructionTimeController */ public final void configureDestruction(final int defaultTime, final DateField defaultTimeUnit, final int maxTime, final DateField maxTimeUnit, final boolean allowModif){ diff --git a/src/uws/service/UWSFactory.java b/src/uws/service/UWSFactory.java index 73507c28a3e0dd48047950199bdb98a155125cc3..64e09fb99149284b2ecf8d0424b167a9bd2c0390 100644 --- a/src/uws/service/UWSFactory.java +++ b/src/uws/service/UWSFactory.java @@ -2,21 +2,21 @@ package uws.service; /* * 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 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * + * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -37,37 +37,43 @@ import uws.service.request.RequestParser; /** * Let's creating UWS jobs, their threads and extracting their parameters from {@link HttpServletRequest}. - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (11/2014) - * + * @version 4.3 (09/2017) + * * @see UWS#getFactory() */ public interface UWSFactory { /** * Creates a (PENDING) UWS job from the given HTTP request. - * + * * @param request Request which triggers the creation of a UWS job. * @param user The identified UWS user (see {@link UserIdentifier}). - * + * * @return The created job. - * + * * @throws UWSException If there is an error while creating the job. */ public UWSJob createJob(final HttpServletRequest request, final JobOwner user) throws UWSException; /** * <p>Creates a UWS job with the following attributes.</p> - * + * * <i> * <ul> - * <li><u>note1:</u> This function is mainly used to restore a UWS job at the UWS initialization.</li> - * <li><u>note2:</u> The job phase is chosen automatically from the given job attributes (i.e. no endTime => PENDING, no result and no error => ABORTED, ...).</li> + * <li><u>note1:</u> This function is mainly used to restore a UWS job + * at the UWS initialization.</li> + * <li><u>note2:</u> The job phase is chosen automatically from the + * given job attributes (i.e. no endTime => + * PENDING, no result and no error => ABORTED, + * ...).</li> * </ul> * </i> - * + * * @param jobID ID of the job (NOT NULL). + * @param creationTime Creation date/time of the job (SHOULD NOT BE + * NEGATIVE OR NULL). * @param owner Owner of the job. * @param params List of all input UWS job parameters. * @param quote Its quote (in seconds). @@ -75,42 +81,44 @@ public interface UWSFactory { * @param endTime Date/Time of the end of this job. * @param results All results of this job. * @param error The error which ended the job to create. - * + * * @return The created job. - * + * * @throws UWSException If there is an error while creating the job. + * + * @since 4.3 */ - public UWSJob createJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException; + public UWSJob createJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException; /** * Creates the thread which will executes the task described by the given {@link UWSJob} instance. - * + * * @param jobDescription Description of the task to execute. - * + * * @return The task to execute. - * + * * @throws UWSException If there is an error while creating the job task. */ public JobThread createJobThread(final UWSJob jobDescription) throws UWSException; /** * Lets extracting all parameters from the given request. - * + * * @param request The request from which parameters must be extracted. - * + * * @return The extracted parameters. - * + * * @throws UWSException If an error occurs while extracting parameters. */ public UWSParameters createUWSParameters(final HttpServletRequest request) throws UWSException; /** * Lets extracting all parameters from the given map. - * + * * @param params All the parameters to check and to store. - * + * * @return The extracted parameters. - * + * * @throws UWSException If an error occurs while extracting parameters. */ public UWSParameters createUWSParameters(final Map<String,Object> params) throws UWSException; @@ -118,13 +126,13 @@ public interface UWSFactory { /** * Create a parser of HTTP requests. This object is able to deal with the different formats * in which parameters are provided in an HTTP request. - * + * * @param manager File manager to use if files are uploaded in an HTTP request. - * + * * @return The request parser to use. - * + * * @throws UWSException If an error occurs while creating the parser. - * + * * @since 4.1 */ public RequestParser createRequestParser(final UWSFileManager manager) throws UWSException; diff --git a/src/uws/service/UWSServlet.java b/src/uws/service/UWSServlet.java index 9c4e2d9d9f2098c66ccbf71068db1f2d67db4653..60355f690ec44d2ba0a6aadd64fee835ac2d83b7 100644 --- a/src/uws/service/UWSServlet.java +++ b/src/uws/service/UWSServlet.java @@ -150,7 +150,7 @@ import uws.service.request.UploadFile; * </p> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.2 (09/2017) + * @version 4.3 (09/2017) */ public abstract class UWSServlet extends HttpServlet implements UWS, UWSFactory { private static final long serialVersionUID = 1L; @@ -775,8 +775,8 @@ public abstract class UWSServlet extends HttpServlet implements UWS, UWSFactory } @Override - public UWSJob createJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{ - return new UWSJob(jobID, owner, params, quote, startTime, endTime, results, error); + public UWSJob createJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{ + return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error); } @Override diff --git a/src/uws/service/backup/DefaultUWSBackupManager.java b/src/uws/service/backup/DefaultUWSBackupManager.java index 021b4784d215683a7cfa8dca7725cad98320db02..327f1423bf6e8b3aad0ea80458e5e2f9bc2d401a 100644 --- a/src/uws/service/backup/DefaultUWSBackupManager.java +++ b/src/uws/service/backup/DefaultUWSBackupManager.java @@ -2,20 +2,20 @@ package uws.service.backup; /* * 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 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -69,7 +69,7 @@ import uws.service.request.UploadFile; /** * <p>Default implementation of the interface {@link UWSBackupManager}.</p> - * + * * <p> * With this class, a UWS can be saved and restored easily thanks to {@link #saveAll()} and {@link #restoreAll()}. * It is saved in JSON and in one or several files in function of the backup mode: @@ -78,16 +78,16 @@ import uws.service.request.UploadFile; * <li><u>by user</u>: one file for each user. The file contains all the information about the user and all the jobs he owns.</li> * <li><u>in one file</u>: one file to describe all users and all the jobs.</li> * </ul> - * + * * <p>The backup frequency can also be changed and may have 2 special values:</p> * <ul> * <li><u>{@link #AT_USER_ACTION} (=0)</u>: only the jobs of the user which has just created, destroyed, executed or stopped a job are saved. This frequency is possible only if the backup mode is <u>by user</u>.</li> * <li><u>{@link #MANUAL} (=-1)</u>: you must call yourself the function {@link #saveAll()} to save the UWS.</li> * </ul> * <p>Another positive value will be considered as the frequency (in milliseconds) of the automatic backup (= {@link #saveAll()}).</p> - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.2 (09/2017) + * @version 4.3 (09/2017) */ public class DefaultUWSBackupManager implements UWSBackupManager { @@ -120,9 +120,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds a backup manager in the mode "auto": one file for all users and all jobs, and the backup * is done all minutes (see {@link #DEFAULT_FREQUENCY}. - * + * * @param uws The UWS to save/restore. - * + * * @see #DefaultUWSBackupManager(UWS, long) */ public DefaultUWSBackupManager(final UWS uws){ @@ -132,12 +132,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * <p>Builds a backup manager in the mode "auto" or "manual": one file for all users and all jobs, and the backup * is done at the given frequency.</p> - * + * * <p>If the given frequency is 0 or negative (see {@link #MANUAL}), the backup will not be done automatically. You must manually * save the UWS thanks to the function {@link #saveAll()}.</p> - * + * * <p>If the given frequency is positive, the backup will be done automatically at the given frequency.</p> - * + * * @param uws The UWS to save/restore. * @param frequency The backup frequency (in ms ; MUST BE positive and different from 0. If negative or 0, the frequency will be automatically set to {@link #DEFAULT_FREQUENCY}). */ @@ -160,12 +160,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds a backup manager in the given mode: "by user" (one file for each user and the backup is done at each user action) * or not (one file for all users and all jobs and the backup is done all minutes (see {@link #DEFAULT_FREQUENCY})). - * + * * @param uws The UWS to save/restore. * @param byUser Backup mode. - * + * * @throws UWSException If the user identification is disabled (that's to say, if the given UWS has no UserIdentifier) while the parameter <i>byUser</i> is <i>true</i>. - * + * * @see #DefaultUWSBackupManager(UWS, boolean, long) */ public DefaultUWSBackupManager(final UWS uws, final boolean byUser) throws UWSException{ @@ -174,11 +174,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds a backup manager in the given mode and with the given frequency. - * + * * @param uws The UWS to save/restore. * @param byUser Backup mode (<i>true</i> means one file for each user and <i>false</i>, one file for all users and jobs). * @param frequency Backup frequency ({@link #AT_USER_ACTION}, {@link #MANUAL}, {@link #DEFAULT_FREQUENCY}, or a positive value). - * + * * @throws UWSException If the user identification is disabled (that's to say, if the given UWS has no UserIdentifier) while the parameter <i>byUser</i> is <i>true</i>. */ public DefaultUWSBackupManager(final UWS uws, final boolean byUser, final long frequency) throws UWSException{ @@ -205,7 +205,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Tells whether this backup manager is enabled or not. - * + * * @return <i>true</i> if the backup is enabled, <i>false</i> otherwise. */ public final boolean isEnabled(){ @@ -237,7 +237,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Gets the backup frequency. - * + * * @return The backup frequency (in milliseconds). */ public final long getBackupFreq(){ @@ -246,7 +246,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * <p>Sets the backup frequency.</p> - * + * * <p> * <i><u>note 1:</u> A negative frequency will be interpreted as "manual".. * that's to say you will have to call yourself the {@link #saveAll()} method to save the UWS. @@ -254,7 +254,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { * <p> * <i><u>note 2:</u> Nothing will be done if the given frequency is {@link #AT_USER_ACTION} although the current backup mode is "by user". * </i></p> - * + * * @param freq The new backup frequency (in milliseconds) ({@link #AT_USER_ACTION}, {@link #MANUAL}, {@link #DEFAULT_FREQUENCY} or any other positive value). */ public final void setBackupFreq(long freq){ @@ -282,7 +282,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Gets the date of the last restoration - * + * * @return The date of the last restoration (MAY BE NULL). */ public final Date getLastRestoration(){ @@ -291,7 +291,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Gets the date of the last backup. - * + * * @return The date of the last backup (MAY BE NULL). */ public final Date getLastBackup(){ @@ -300,9 +300,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Gets the logger of its UWS, or the default one if it is unknown. - * + * * @return A logger. - * + * * @see UWS#getLogger() * @see UWSToolBox#getDefaultLogger() */ @@ -495,7 +495,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * <p>Serializes the given user into a JSON object.</p> - * + * * <pre> * { * "id": "...", @@ -508,11 +508,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager { * the last suspension points mean that other user data may be added into this JSON object. * These other user data to save MUST BE given by {@link JobOwner#getDataToSave()}. * </i></p> - * + * * @param user The user to save. - * + * * @return Its JSON representation. - * + * * @throws JSONException If there is an error while building the JSON object. */ protected JSONObject getJSONUser(final JobOwner user) throws JSONException{ @@ -531,18 +531,18 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * <p>Serializes the given job into a JSON object.</p> - * + * * <p> * <i><u>note</u>: * the structure of the returned JSON object is decided by {@link Json4Uws#getJson(UWSJob)}. * Only one attribute is added: "jobListName". * </i></p> - * + * * @param job The job to save. * @param jlName Name of the jobs list containing the given job. - * + * * @return The JSON representation of the given job. - * + * * @throws UWSException If there is an error while getting job parameters and serializing them. * @throws JSONException If there is an error while building the JSON object. */ @@ -592,20 +592,20 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Serialize the given {@link JobInfo} so that being able later to restore this exact object as provided. - * + * * <p><i> * By default, this function use the Java Class serialization (see {@link Serializable}) * and save the corresponding bytes into a Base-64 string. * </i></p> - * + * * @param jobInfo The jobInfo to backup. - * + * * @return The string to use in order to restore the given jobInfo * (e.g. a Base-64 serialization of the Java Object, a URL, ...). - * + * * @throws UWSException If any error occurs while representing the given {@link JobInfo}. * @throws JSONException If any error occurs while manipulating a JSON object or array. - * + * * @since 4.2 */ protected Object getJSONJobInfo(final JobInfo jobInfo) throws UWSException, JSONException{ @@ -635,19 +635,19 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Restore the JobInfo referenced or represented by the given JSON value. - * + * * <p><i> * By default, this function considers that the given value is a Base-64 string encoding * the Java Class serialization (see {@link Serializable}) of the {@link JobInfo} to restore. * </i></p> - * + * * @param jsonValue The reference or backup representation of the {@link JobInfo} to restore. - * + * * @return The restored {@link JobInfo}. - * + * * @throws UWSException If any error occurs while restoring the {@link JobInfo}. * @throws JSONException If any error occurs while manipulating a JSON object or array. - * + * * @since 4.2 */ protected JobInfo restoreJobInfo(final Object jsonValue) throws UWSException, JSONException{ @@ -669,13 +669,13 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Get the JSON representation of the given {@link UploadFile}. - * + * * @param upl The uploaded file to serialize in JSON. - * + * * @return Its JSON representation. - * + * * @throws JSONException If there is an error while building the JSON object. - * + * * @since 4.1 */ protected JSONObject getUploadJson(final UploadFile upl) throws JSONException{ @@ -855,13 +855,13 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the instance of {@link JobOwner} corresponding to the given JSON object. - * + * * @param json JSON representation of the user to build. - * + * * @return The corresponding instance of {@link JobOwner} or <i>null</i> if the given object is empty. - * + * * @throws UWSException If the "id" parameter is missing (a user MUST have an id ; warning: the case sensitivity is enabled only for this attribute). - * + * * @see JobOwner#restoreData(Map) */ protected JobOwner getUser(final JSONObject json) throws UWSException{ @@ -894,12 +894,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the job corresponding to the given JSON object and then restore it in the UWS. - * + * * @param json The JSON representation of the job to restore. * @param users The list of all fetched users. - * + * * @return <i>true</i> if the corresponding job has been successfully restored, <i>false</i> otherwise. - * + * * @throws UWSException If the job ID or the job list name is missing, * or if the job list name is incorrect, * or if there is an error with "parameters", "error" and "results". @@ -912,7 +912,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { //Date destruction=null; long quote = UWSJob.UNLIMITED_DURATION, /*duration = UWSJob.UNLIMITED_DURATION, */startTime = -1, - endTime = -1; + endTime = -1, creationTime = -1; HashMap<String,Object> inputParams = new HashMap<String,Object>(10); //Map<String, Object> params = null; List<Result> results = null; @@ -948,7 +948,17 @@ public class DefaultUWSBackupManager implements UWSBackupManager { else if (key.equalsIgnoreCase(UWSJob.PARAM_QUOTE)) quote = json.getLong(key); - // key=EXECUTION_DURATION: + // key=CREATION_TIME: + else if (key.equalsIgnoreCase(UWSJob.PARAM_CREATION_TIME)){ + tmp = json.getString(key); + try{ + Date d = ISO8601Format.parseToDate(tmp); + creationTime = d.getTime(); + }catch(ParseException pe){ + getLogger().logUWS(LogLevel.ERROR, json, "RESTORATION", "Incorrect date format for the '" + key + "' parameter!", pe); + } + + }// key=EXECUTION_DURATION: else if (key.equalsIgnoreCase(UWSJob.PARAM_EXECUTION_DURATION)){ long duration = json.getLong(key); inputParams.put(UWSJob.PARAM_EXECUTION_DURATION, duration); @@ -1061,7 +1071,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { } // Create the job: - UWSJob job = uws.getFactory().createJob(jobId, owner, uwsParams, quote, startTime, endTime, results, error); + UWSJob job = uws.getFactory().createJob(jobId, creationTime, owner, uwsParams, quote, startTime, endTime, results, error); // Set its jobInfo, if any: if (jobInfo != null) @@ -1081,15 +1091,15 @@ public class DefaultUWSBackupManager implements UWSBackupManager { * Restores other job parameters, either from the given JSON object or from the parameters map of the given job. * The job is supposed to be updated after the call of this function. * </p> - * + * * <p><i><u>note:</u> By default, this function does nothing ! It is called by {@link #restoreJob(JSONObject, Map)} * just after the default restoration from the given JSON and just before to add the job in its dedicated jobs list.</i></p> - * + * * @param json JSON backup of the given job. * @param job Default restoration of the job. - * + * * @throws UWSException If there is an error while restoring other job parameters. - * + * * @see #restoreJob(JSONObject, Map) */ protected void restoreOtherJobParams(final JSONObject json, final UWSJob job) throws UWSException{ @@ -1098,9 +1108,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the list of parameters corresponding to the given JSON object. - * + * * @param obj The JSON representation of a parameters list. - * + * * @return The corresponding list of parameters * or <i>null</i> if the given object is empty. */ @@ -1122,11 +1132,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Build the upload file corresponding to the given JSON object. - * + * * @param obj The JSON representation of the {@link UploadFile} to get. - * + * * @return The corresponding {@link UploadFile}. - * + * * @since 4.1 */ protected UploadFile getUploadFile(final JSONObject obj){ @@ -1147,14 +1157,14 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the list of results corresponding to the given JSON array. - * + * * @param array The JSON representation of the results to restore. - * + * * @return The corresponding list of results * or <i>null</i> if the array is empty. - * + * * @throws UWSException If there is an error while restoring one of the result. - * + * * @see #getResult(JSONObject) */ protected List<Result> getResults(final JSONArray array) throws UWSException{ @@ -1177,11 +1187,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the result corresponding to the given JSON object. - * + * * @param obj The JSON representation of the result to restore. - * + * * @return The corresponding result or <i>null</i> if the given object is empty. - * + * * @throws JSONException If there is an error while reading the JSON. * @throws UWSException */ @@ -1223,11 +1233,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Builds the error summary corresponding to the given JSON object. - * + * * @param obj The JSON representation of the error summary to restore. - * + * * @return The corresponding error summary or <i>null</i> if the given object is empty. - * + * * @throws UWSException */ protected ErrorSummary getError(final JSONObject obj) throws UWSException{ @@ -1267,7 +1277,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { * as an iterator which returns all the keys. The value of each key can be fetched thanks to * the different available getters (i.e. {@link #getJSONArray()}, {@link #getJSONObject()}, * {@link #getValue()}, {@link #getString()}, ...). - * + * * @author Grégory Mantelet (CDS) * @version 05/2012 */ @@ -1417,7 +1427,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * Lets reading a JSON array from a {@link JSONTokener} (that's to directly from a file) * as an iterator <b>which returns all items which MUST BE {@link JSONObject}s</b>. - * + * * @author Grégory Mantelet (CDS) * @version 05/2012 */ @@ -1515,10 +1525,10 @@ public class DefaultUWSBackupManager implements UWSBackupManager { /** * An iterator of input streams with ONLY ONE input stream. - * + * * @author Grégory Mantelet (CDS) * @version 05/2012 - * + * * @see DefaultUWSBackupManager#restoreAll() */ protected final static class SingleInputIterator implements Iterator<InputStream> {