diff --git a/src/tap/TAPJob.java b/src/tap/TAPJob.java
index 5c4a405e2380e29e4616e2b369485ff4fa974422..5eaa5ceb5d7757003e992af9c0da72bd46bea3af 100644
--- a/src/tap/TAPJob.java
+++ b/src/tap/TAPJob.java
@@ -53,42 +53,55 @@ import uws.service.log.UWSLog.LogLevel;
 public class TAPJob extends UWSJob {
 	private static final long serialVersionUID = 1L;
 
-	/** Name of the standard TAP parameter which specifies the type of request to execute: "REQUEST". */
+	/** Name of the standard TAP parameter which specifies the type of request
+	 * to execute: "REQUEST". */
 	public static final String PARAM_REQUEST = "request";
 	/** REQUEST value meaning an ADQL query must be executed: "doQuery". */
 	public static final String REQUEST_DO_QUERY = "doQuery";
-	/** REQUEST value meaning VO service capabilities must be returned: "getCapabilities". */
+	/** REQUEST value meaning VO service capabilities must be returned:
+	 * "getCapabilities". */
 	public static final String REQUEST_GET_CAPABILITIES = "getCapabilities";
 
-	/** Name of the standard TAP parameter which specifies the query language: "LANG". <i>(only the ADQL language is supported by default in this version of the library)</i> */
+	/** Name of the standard TAP parameter which specifies the query language:
+	 * "LANG". <i>(only the ADQL language is supported by default in this
+	 * version of the library)</i> */
 	public static final String PARAM_LANGUAGE = "lang";
 	/** LANG value meaning ADQL language: "ADQL". */
 	public static final String LANG_ADQL = "ADQL";
-	/** LANG value meaning PQL language: "PQL". <i>(this language is not supported in this version of the library)</i> */
+	/** LANG value meaning PQL language: "PQL". <i>(this language is not
+	 * supported in this version of the library)</i> */
 	public static final String LANG_PQL = "PQL";
 
-	/** Name of the standard TAP parameter which specifies the version of the TAP protocol that must be used: "VERSION". <i>(only the version 1.0 is supported in this version of the library)</i> */
+	/** Name of the standard TAP parameter which specifies the version of the
+	 * TAP protocol that must be used: "VERSION". <i>(only the version 1.0 is
+	 * supported in this version of the library)</i> */
 	public static final String PARAM_VERSION = "version";
 	/** VERSION value meaning the version 1.0 of TAP: "1.0". */
 	public static final String VERSION_1_0 = "1.0";
 
-	/** Name of the standard TAP parameter which specifies the output format (format of a query result): "FORMAT". */
+	/** Name of the standard TAP parameter which specifies the output format
+	 * (format of a query result): "FORMAT". */
 	public static final String PARAM_FORMAT = "format";
 	/** FORMAT value meaning the VOTable format: "votable". */
 	public static final String FORMAT_VOTABLE = "votable";
 
-	/** Name of the standard TAP parameter which specifies the maximum number of rows that must be returned in the query result: "MAXREC". */
+	/** Name of the standard TAP parameter which specifies the maximum number of
+	 * rows that must be returned in the query result: "MAXREC". */
 	public static final String PARAM_MAX_REC = "maxRec";
 	/** Special MAXREC value meaning the number of output rows is not limited. */
 	public static final int UNLIMITED_MAX_REC = -1;
 
-	/** Name of the standard TAP parameter which specifies the query to execute: "QUERY". */
+	/** Name of the standard TAP parameter which specifies the query to execute:
+	 * "QUERY". */
 	public static final String PARAM_QUERY = "query";
 
-	/** Name of the standard TAP parameter which defines the tables to upload in the database for the query execution: "UPLOAD". */
+	/** Name of the standard TAP parameter which defines the tables to upload in
+	 * the database for the query execution: "UPLOAD". */
 	public static final String PARAM_UPLOAD = "upload";
 
-	/** Name of the library parameter which informs about a query execution progression: "PROGRESSION". <i>(this parameter is removed once the execution is finished)</i> */
+	/** Name of the library parameter which informs about a query execution
+	 * progression: "PROGRESSION". <i>(this parameter is removed once the
+	 * execution is finished)</i> */
 	public static final String PARAM_PROGRESSION = "progression";
 
 	/** Internal query execution report. */
@@ -98,15 +111,20 @@ public class TAPJob extends UWSJob {
 	protected final TAPParameters tapParams;
 
 	/**
-	 * <p>Build a pending TAP job with the given parameters.</p>
+	 * Build a pending TAP job with the given 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>Note:
+	 * 	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.
+	 * @throws TAPException	If one of the given parameters has a forbidden or
+	 *                     	wrong value.
 	 */
 	public TAPJob(final JobOwner owner, final TAPParameters tapParams) throws TAPException{
 		super(owner, tapParams);
@@ -115,18 +133,26 @@ 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>
+	 * 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><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>Note:
+	 * 	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>
+	 * @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.
+	 * @throws TAPException	If one of the given parameters has a forbidden or
+	 *                     	wrong value.
 	 *
 	 * @since 2.1
 	 */
@@ -138,11 +164,13 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * 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.
+	 * 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 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 ;
@@ -169,7 +197,8 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * Get the object storing and managing the set of all (UWS and TAP) parameters.
+	 * Get the object storing and managing the set of all (UWS and TAP)
+	 * parameters.
 	 *
 	 * @return The object managing all job parameters.
 	 */
@@ -178,7 +207,7 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the value of the REQUEST parameter.</p>
+	 * Get the value of the REQUEST parameter.
 	 *
 	 * <p>This value must be {@value #REQUEST_DO_QUERY}.</p>
 	 *
@@ -198,9 +227,12 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the value of the LANG parameter.</p>
+	 * Get the value of the LANG parameter.
 	 *
-	 * <p>This value should always be {@value #LANG_ADQL} in this version of the library</p>
+	 * <p>
+	 * 	This value should always be {@value #LANG_ADQL} in this version of the
+	 * 	library
+	 * </p>
 	 *
 	 * @return	LANG value.
 	 */
@@ -209,9 +241,12 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the value of the MAXREC parameter.</p>
+	 * Get the value of the MAXREC parameter.
 	 *
-	 * <p>If this value is negative, it means the number of output rows is not limited.</p>
+	 * <p>
+	 * 	If this value is negative, it means the number of output rows is not
+	 * 	limited.
+	 * </p>
 	 *
 	 * @return	MAXREC value.
 	 */
@@ -220,7 +255,8 @@ 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).
+	 * Get the value of the QUERY parameter (i.e. the query, in the language
+	 * returned by {@link #getLanguage()}, to execute).
 	 *
 	 * @return	QUERY value.
 	 */
@@ -229,9 +265,12 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the value of the VERSION parameter.</p>
+	 * Get the value of the VERSION parameter.
 	 *
-	 * <p>This value should be {@value #VERSION_1_0} in this version of the library.</p>
+	 * <p>
+	 * 	This value should be {@value #VERSION_1_0} in this version of the
+	 * 	library.
+	 * </p>
 	 *
 	 * @return	VERSION value.
 	 */
@@ -240,9 +279,12 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the value of the UPLOAD parameter.</p>
+	 * Get the value of the UPLOAD parameter.
 	 *
-	 * <p>This value must be formatted as specified by the TAP standard (= a semicolon separated list of DALI uploads).</p>
+	 * <p>
+	 * 	This value must be formatted as specified by the TAP standard (= a
+	 * 	semicolon separated list of DALI uploads).
+	 * </p>
 	 *
 	 * @return	UPLOAD value.
 	 */
@@ -251,7 +293,7 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the list of tables to upload in the database for the query execution.</p>
+	 * Get the list of tables to upload in the database for the query execution.
 	 *
 	 * <p>The returned array is an interpretation of the UPLOAD parameter.</p>
 	 *
@@ -262,12 +304,13 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Get the execution report.</p>
+	 * Get the execution report.
 	 *
 	 * <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.
+	 * 	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.
@@ -277,16 +320,18 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Set the execution report.</p>
+	 * Set the execution report.
 	 *
 	 * <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.
+	 * 	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.
+	 * @throws UWSException	If this job has never been restored and is not
+	 *                     	running.
 	 */
 	public final void setExecReport(final TAPExecutionReport execReport) throws UWSException{
 		if (getRestorationDate() == null && (thread == null || thread.isFinished()))
@@ -295,11 +340,14 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Create the thread to use for the execution of this job.</p>
+	 * Create the thread to use for the execution of this job.
 	 *
-	 * <p><i>Note: If the job already exists, this function does nothing.</i></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 NullPointerException	If the factory returned NULL rather than the
+	 *                             	asked {@link JobThread}.
 	 * @throws UWSException			If the thread creation fails.
 	 *
 	 * @see TAPFactory#createJobThread(UWSJob)
@@ -315,18 +363,23 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Check whether this job is able to start right now.</p>
+	 * Check whether this job is able to start right now.
 	 *
 	 * <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.
+	 * 	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>
+	 * <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.
+	 * </p>
 	 *
-	 * @return	<i>true</i> if this job can start right now, <i>false</i> otherwise.
+	 * @return	<i>true</i> if this job can start right now,
+	 *        	<i>false</i> otherwise.
 	 *
 	 * @since 2.0
 	 */
@@ -363,6 +416,7 @@ public class TAPJob extends UWSJob {
 			}
 
 			// Change the job phase:
+			setPhase(ExecutionPhase.QUEUED);
 			setPhase(ExecutionPhase.EXECUTING);
 
 			// Set the start time:
@@ -403,7 +457,8 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * This exception is thrown by a job execution when no database connection are available anymore.
+	 * This exception is thrown by a job execution when no database connection
+	 * are available anymore.
 	 *
 	 * @author Gr&eacute;gory Mantelet (ARI)
 	 * @version 2.0 (02/2015)
diff --git a/src/uws/job/JobDestructionPolicy.java b/src/uws/job/JobDestructionPolicy.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b76d1c961d00b6f57cccc234eac8e557d8889db
--- /dev/null
+++ b/src/uws/job/JobDestructionPolicy.java
@@ -0,0 +1,97 @@
+package uws.job;
+
+/*
+ * 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 2017 - Astronomisches Rechen Institut (ARI)
+ */
+
+import uws.job.user.JobOwner;
+
+/**
+ * Behavior to apply when a job destruction is asked.
+ *
+ * <p>
+ * 	This policy must be set individually on {@link JobList} instances.
+ * 	Thus, the jobs lists of a UWS service may have a different behavior when a
+ * 	job destruction is required.
+ * </p>
+ *
+ * @author Gr&eacute;gory Mantelet (ARI)
+ * @version 4.3 (09/2017)
+ * @since 4.3
+ *
+ * @since {@link JobList#destroyJob(String)}
+ * @since {@link JobList#destroyJob(String, JobOwner)}
+ */
+public enum JobDestructionPolicy{
+	/**
+	 * <p><i><b>Default behavior in UWS-1.0 (and in UWSLibrary).</b></i></p>
+	 *
+	 * <p>
+	 * 	Jobs are ALWAYS immediately destroyed and removed from the
+	 * 	{@link JobList}.
+	 * </p>
+	 */
+	ALWAYS_DELETE,
+	/**
+	 * <p><i><b>
+	 * 	Behavior described in UWS-1.1 about the ARCHIVED phase.
+	 * </b></i></p>
+	 *
+	 * <p>
+	 * 	Jobs are archived when the destruction date is reached.
+	 * </p>
+	 *
+	 * <p>
+	 * 	The archived jobs are then still in the {@link JobList}
+	 * 	but in the {@link ExecutionPhase#ARCHIVED} phase. An archived job is
+	 * 	stopped and all its resources (uploads, results and threads) are freed.
+	 * </p>
+	 * <p>
+	 * 	If the destruction date is yet not reached, the job is merely destroyed
+	 * 	and removed from the {@link JobList}.
+	 * </p>
+	 * <p><i>Note:
+	 * 	Destroying an archived job will definitely destroy it. Thus, the real
+	 * 	destruction of a job may be done in 2 steps while using this policy.
+	 * </i></p>
+	 */
+	ARCHIVE_ON_DATE,
+	/**
+	 * <p><i><b>
+	 * 	Alternative behavior proposed by UWSLibrary (but never described in any
+	 * 	UWS standard document).
+	 * </b></i></p>
+	 *
+	 * <p>
+	 * 	Jobs are ALWAYS immediately archived when a destruction is required
+	 * 	(either because the destruction is reached or because of an explicit
+	 * 	 action of the UWS client).
+	 * </p>
+	 *
+	 * <p>
+	 * 	The archived jobs are then still in the {@link JobList} but in the
+	 * 	{@link ExecutionPhase#ARCHIVED} phase. An archived job is stopped and
+	 * 	all its resources (uploads, results and threads) are freed.
+	 * </p>
+	 * <p><i>Note:
+	 * 	Destroying an archived job will definitely destroy it. Thus, the real
+	 * 	destruction of a job must be done in 2 steps while using this policy.
+	 * </i></p>
+	 */
+	ALWAYS_ARCHIVE;
+}
diff --git a/src/uws/job/JobList.java b/src/uws/job/JobList.java
index 65117f2e170e7f61da0cf5f1f0e3f1e0fbb8c03d..3923c4a214940a6151e823310d5db3008de796e3 100644
--- a/src/uws/job/JobList.java
+++ b/src/uws/job/JobList.java
@@ -2,25 +2,26 @@ package uws.job;
 
 /*
  * 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)
  */
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -45,65 +46,142 @@ import uws.service.log.UWSLog.LogLevel;
 
 /**
  * <h3>General description</h3>
- * 
- * <p>An instance of this class lets listing UWS jobs (possible actions: get, add and remove).</p>
- * 
- * <p><i><u>Note:</u>This list implements the interface {@link Iterable} which lets you iterating more easily among the jobs.</i></p>
- * 
+ *
+ * <p>
+ * 	An instance of this class lets listing UWS jobs (possible actions: get, add
+ * 	and remove).
+ * </p>
+ *
+ * <p><i>Note:
+ * 	This list implements the interface {@link Iterable} which lets you iterating
+ * 	more easily among the jobs.
+ * </i></p>
+ *
  * <h3>Jobs list by user</h3>
- * 
- * <p>So that avoiding any user to interact on jobs of anybody else, it is possible (and strongly encouraged)
- * to get the list of jobs only of the current user. For that you must use the function {@link #getJobs(JobOwner)} with a owner ID.</p>
- * 
- * <p>At each request sent to any instance of {@link UWSService} the function {@link UserIdentifier#extractUserId(uws.service.UWSUrl, javax.servlet.http.HttpServletRequest)}
- * may extract the user ID. Thus the action GetJobList may know who is the current user. If the extracted owner ID is different from <i>null</i>
- * only the jobs of the current user will be returned.<br />
- * <b>However you need to find a way to identify for each UWS request the current user and then to override correctly the function
- * {@link UserIdentifier#extractUserId(uws.service.UWSUrl, javax.servlet.http.HttpServletRequest)}.</b></p>
- * 
- * <p><i><u>Note:</u> if no owner is specified (NULL value), all jobs are concerned by the function action.</i></p>
- * 
+ *
+ * <p>
+ * 	So that avoiding any user to interact on jobs of anybody else, it is
+ * 	possible (and strongly encouraged) to get the list of jobs only of the
+ * 	current user. For that you must use the function {@link #getJobs(JobOwner)}
+ * 	with a owner ID.
+ * </p>
+ *
+ * <p>
+ * 	At each request sent to any instance of {@link UWSService} the function
+ * 	{@link UserIdentifier#extractUserId(uws.service.UWSUrl, javax.servlet.http.HttpServletRequest)}
+ * 	may extract the user ID. Thus the action GetJobList may know who is the
+ * 	current user. If the extracted owner ID is different from <i>null</i> only
+ * 	the jobs of the current user will be returned.
+ * </p>
+ * <p><b>WARNING:</b>
+ * 	You need to find a way to identify for each UWS request the current user and
+ * 	then to override correctly the function
+ * 	{@link UserIdentifier#extractUserId(uws.service.UWSUrl, javax.servlet.http.HttpServletRequest)}.
+ * </p>
+ *
+ * <p><i>Note:
+ * 	If no owner is specified (NULL value), all jobs are concerned by the
+ * 	function action.
+ * </i></p>
+ *
  * <h3>Searching in a jobs list</h3>
- * 
+ *
  * <ul>
- * 	<li><b>{@link #getJobs()} or {@link #iterator()}:</b> to get all the jobs of this jobs list.</li>
- * 	<li><b>{@link #getJob(String)}:</b> to get the job that has the given jobID.</li>
- * 	<li><b>{@link #searchJobs(String)}:</b> to search all the jobs that have the given runID.</li>
- * 	<li><b>{@link #getJobs(JobOwner)}: </b> to get the jobs of the specified user.</li>
+ * 	<li><b>{@link #getJobs()} or {@link #iterator()}:</b> to get all the jobs of
+ * 	                                                      this jobs list.</li>
+ * 	<li><b>{@link #getJob(String)}:</b> to get the job that has the given
+ * 	                                    jobID.</li>
+ * 	<li><b>{@link #searchJobs(String)}:</b> to search all the jobs that have the
+ * 	                                        given runID.</li>
+ * 	<li><b>{@link #getJobs(JobOwner)}:</b> to get the jobs of the specified
+ * 	                                        user.</li>
  * </ul>
- * 
+ *
  * <h3>Get the users list</h3>
- * 
- * <p>If you are interested in (probably for some statistics or for an administrator) you can ask the list of users
- * who have at least one job in this jobs list ({@link #getUsers()}) and known how many they are ({@link #getNbUsers()}).</p>
- * 
+ *
+ * <p>
+ * 	If you are interested in (probably for some statistics or for an
+ * 	administrator) you can ask the list of users who have at least one job in
+ * 	this jobs list ({@link #getUsers()}) and known how many they are
+ * 	({@link #getNbUsers()}).
+ * </p>
+ *
  * <h3>Execution management</h3>
- * 
- * <p>The execution of the jobs of this jobs list is managed by an implementation of {@link ExecutionManager}.
- * {@link DefaultExecutionManager} is used by default, but you can easily set your owne implementation of this interface,
- * either at the job list creation or with {@link #setExecutionManager(ExecutionManager)}.</p>
- * 
+ *
+ * <p>
+ * 	The execution of the jobs of this jobs list is managed by an implementation
+ * 	of {@link ExecutionManager}. {@link DefaultExecutionManager} is used by
+ * 	default, but you can easily set your own implementation of this interface,
+ * 	either at the job list creation or with
+ * 	{@link #setExecutionManager(ExecutionManager)}.
+ * </p>
+ *
  * <h3>Automatic job destruction</h3>
- * 
+ *
+ * <p>
+ * 	A job has a field - destructionTime - which indicates the date at which it
+ * 	must be destroyed. Remember that destroying a job consists in removing it
+ * 	from its jobs list and then clearing all its resources (result and input
+ * 	files, threads, ...). This task is done by an "instance" of the interface
+ * 	{@link DestructionManager}. By default a jobs list has a default
+ * 	implementation of this interface: {@link DefaultDestructionManager}.
+ * </p>
+ * <p><b>WARNING:</b>
+ * 	When added in a UWS, the jobs list inherits the destruction manager of its
+ * 	UWS. Thus all jobs list of a UWS have the same destruction manager.
+ * </p>
+ *
+ * <p>
+ * 	To use a custom destruction manager, you can use the method
+ * 	{@link #setDestructionManager(DestructionManager)}.
+ * </p>
+ *
+ * <h3>Archiving and Job destruction policy</h3>
+ *
+ * <p>
+ * 	Since UWS-1.1, it is possible to archive a job. The behavior described in
+ * 	the UWS-1.1 document is that a job goes into the ARCHIVED phase when its
+ * 	destruction date is reached. This behavior is a destruction alternative
+ * 	introduced in order to keep only the metadata part of a job whenever it
+ * 	is automatically destroyed by the UWS service. It is not imposed in the
+ * 	UWS-1.1 document ; it is just a description of the ARCHIVED phase.
+ * </p>
+ *
  * <p>
- * 	A job has a field - destructionTime - which indicates the date at which it must destroyed.
- * 	Remember that destroying a job consists in removing it from its jobs list and then clearing all its resources (result files, threads, ...).
- * 	This task is done by an "instance" of the interface {@link DestructionManager}. By default a jobs list has a default implementation of this interface: {@link DefaultDestructionManager}.
- * 	However when added in a UWS, the jobs list inherits the destruction manager of its UWS. Thus all jobs list of a UWS have the same destruction manager.
+ * 	The UWS Library proposes 2 other strategies: always delete a job
+ * 	(whatever its destruction date is reached or not ; default behavior in
+ * 	UWS 1.0), or always archive first. Thus, it is now possible to specify on a
+ * 	{@link JobList} instance which policy should be used. This can be done
+ * 	thanks to the function {@link #setDestructionPolicy(JobDestructionPolicy)}
+ * 	and with the enum class {@link JobDestructionPolicy}.
  * </p>
- * 
+ *
  * <p>
- * 	To use a custom destruction manager, you can use the method {@link #setDestructionManager(DestructionManager)}.
+ * 	By default, the default behavior proposed by UWS 1.1 is set:
+ * 	{@link JobDestructionPolicy#ALWAYS_DELETE}, mainly for backward
+ * 	compatibility with former library versions but also to prevent using more
+ * 	and more memory for ARCHIVED jobs without the explicit approval from the
+ * 	UWS service manager.
  * </p>
- * 
+ *
+ * <p><i>Note:
+ * 	An archived job can be destroyed definitely by calling again
+ * 	{@link #destroyJob(String)} (i.e. DELETE on {jobs}/{job-id} or POST
+ * 	ACTION=DELETE on {jobs}/{job-id}).
+ * </i></p>
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.2 (09/2017)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see UWSJob
  */
 public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	private static final long serialVersionUID = 1L;
 
+	/** Default policy applied to a job list when a job destruction is asked.
+	 * @since 4.3 */
+	public final static JobDestructionPolicy DEFAULT_JOB_DESTRUCTION_POLICY = JobDestructionPolicy.ALWAYS_DELETE;
+
 	/** <b>[Required]</b> Name of the jobs list. */
 	private final String name;
 
@@ -113,10 +191,20 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	/** <b>[Required]</b> List of jobs per owner. */
 	protected final Map<JobOwner,Map<String,UWSJob>> ownerJobs;
 
-	/** The destruction manager to use to take into account the destructionTime field of contained jobs. */
+	/** The destruction manager to use to take into account the destructionTime
+	 * field of contained jobs. */
 	private DestructionManager destructionManager = null;
 
-	/** This object, if not null, decides whether a managed job can start immediately or must be put in a queue. */
+	/** Indicate how this job list behaves when a job destruction is asked.
+	 * <p>
+	 * 	By default, a job is always destroyed (i.e. when the destruction is
+	 * 	reached but also when a user requested it).
+	 * </p>
+	 * @since 4.3 */
+	private JobDestructionPolicy destructionPolicy = DEFAULT_JOB_DESTRUCTION_POLICY;
+
+	/** This object, if not null, decides whether a managed job can start
+	 * immediately or must be put in a queue. */
 	private ExecutionManager executionManager = null;
 
 	/** <b>[Optional]</b> Useful only to get the URL of this job list. */
@@ -126,12 +214,12 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	/* CONSTRUCTORS */
 	/* ************ */
 	/**
-	 * <p>Builds a jobs list with its name.</p>
-	 * 
-	 * @param jobListName				The jobs list name.
-	 * 
+	 * Builds a jobs list with its name.
+	 *
+	 * @param jobListName	The jobs list name.
+	 *
 	 * @throws NullPointerException	If the given job list name is NULL.
-	 * 
+	 *
 	 * @see #JobList(String, ExecutionManager)
 	 */
 	public JobList(String jobListName) throws NullPointerException{
@@ -140,11 +228,14 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Builds a jobs list with its name and the job list manager.
-	 * 
+	 *
 	 * @param jobListName		The jobs list name.
-	 * @param executionManager	The object which will manage the execution of all jobs of this list.
+	 * @param executionManager	The object which will manage the execution of
+	 *                        	all jobs of this list.
 	 *
-	 * @throws NullPointerException	If the given job list name is NULL or empty or if no execution manager is provided.
+	 * @throws NullPointerException	If the given job list name is NULL
+	 *                             	or empty
+	 *                             	or if no execution manager is provided.
 	 */
 	public JobList(String jobListName, ExecutionManager executionManager) throws NullPointerException{
 		this(jobListName, executionManager, new DefaultDestructionManager());
@@ -152,24 +243,34 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Builds a jobs list with its name and the destruction manager to use.
-	 * 
+	 *
 	 * @param jobListName			The jobs list name.
-	 * @param destructionManager	The object which manages the automatic destruction of jobs when they have reached their destruction date.
+	 * @param destructionManager	The object which manages the automatic
+	 *                          	destruction of jobs when they have reached
+	 *                          	their destruction date.
 	 *
-	 * @throws NullPointerException	If the given job list name is NULL or empty or if no destruction manager is provided.
+	 * @throws NullPointerException	If the given job list name is NULL
+	 *                             	or empty
+	 *                             	or if no destruction manager is provided.
 	 */
 	public JobList(String jobListName, DestructionManager destructionManager) throws NullPointerException{
 		this(jobListName, new DefaultExecutionManager(), destructionManager);
 	}
 
 	/**
-	 * Builds a jobs list with its name, the job list manager and the destruction manager.
-	 * 
+	 * Builds a jobs list with its name, the job list manager and the
+	 * destruction manager.
+	 *
 	 * @param jobListName			The jobs list name.
-	 * @param executionManager		The object which will manage the execution of all jobs of this list.
-	 * @param destructionManager	The object which manages the automatic destruction of jobs when they have reached their destruction date.
+	 * @param executionManager		The object which will manage the execution
+	 *                        		of all jobs of this list.
+	 * @param destructionManager	The object which manages the automatic
+	 *                          	destruction of jobs when they have reached
+	 *                          	their destruction date.
 	 *
-	 * @throws NullPointerException	If the given job list name is NULL or empty or if no execution manager and destruction manager are provided.
+	 * @throws NullPointerException	If the given job list name is NULL or empty
+	 *                             	or if no execution manager and destruction
+	 *                             	manager are provided.
 	 */
 	public JobList(String jobListName, ExecutionManager executionManager, DestructionManager destructionManager) throws NullPointerException{
 		if (jobListName == null)
@@ -197,22 +298,28 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	/* ******************* */
 	/**
 	 * Gets the UWS which manages this jobs list.
-	 * 
-	 * @return	Its UWS or <i>null</i> if this jobs list is not yet part of a specific UWS).
+	 *
+	 * @return	Its UWS or <i>null</i> if this jobs list is not yet part of a
+	 *        	specific UWS).
 	 */
 	public final UWS getUWS(){
 		return uws;
 	}
 
 	/**
-	 * <p>Sets the UWS which aims to manage this jobs list.</p>
-	 * 
-	 * <p><i><u>note:</u> The UWS association can be changed ONLY IF the jobs list is not yet associated with a UWS
-	 * OR IF it is empty.</i></p>
-	 * 
-	 * @param newUws	Its new UWS. <i><u>note:</u> if NULL, nothing is done !</i>
-	 * 
-	 * @throws IllegalStateException	If this jobs list is already associated with a UWS (different from the given one) and contains some jobs.
+	 * Sets the UWS which aims to manage this jobs list.
+	 *
+	 * <p><i>Note:
+	 * 	The UWS association can be changed ONLY IF the jobs list is not yet
+	 * 	associated with a UWS OR IF it is empty.
+	 * </i></p>
+	 *
+	 * @param newUws	Its new UWS.
+	 *              	<i>If NULL, nothing is done!</i>
+	 *
+	 * @throws IllegalStateException	If this jobs list is already associated
+	 *                              	with a UWS (different from the given
+	 *                              	one) and contains some jobs.
 	 */
 	public final void setUWS(UWS newUws) throws IllegalStateException{
 		if (newUws == null)
@@ -227,9 +334,9 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the logger of its UWS, or a default one if the UWS is unknown.
-	 * 
+	 *
 	 * @return A logger.
-	 * 
+	 *
 	 * @see #getUWS()
 	 * @see UWS#getLogger()
 	 * @see UWSToolBox#getDefaultLogger()
@@ -242,10 +349,13 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * <p>Gets the used destruction manager.</p>
-	 * 
-	 * <p><i><u>Note:</u> Remember that the destruction manager lets destroying automatically jobs only when their destructionTime has been reached.</i></p>
-	 * 
+	 * Gets the used destruction manager.
+	 *
+	 * <p><i>Note:
+	 * 	Remember that the destruction manager lets destroying automatically jobs
+	 * 	only when their destructionTime has been reached.
+	 * </i></p>
+	 *
 	 * @return	Its destruction manager.
 	 */
 	public final DestructionManager getDestructionManager(){
@@ -253,15 +363,21 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
+	 * Sets the destruction manager to use.
+	 *
 	 * <p>
-	 * 	Sets the destruction manager to use.
-	 * 	All the jobs are removed from the former destruction manager and then added in the new one.
+	 * 	All the jobs are removed from the former destruction manager and then
+	 * 	added in the new one.
 	 * </p>
-	 * 
-	 * <p><i><u>Note:</u> Remember that the destruction manager lets destroying automatically jobs only when their destructionTime has been reached.</i></p>
-	 * 
-	 * @param newManager	Its new destruction manager (MUST be different from <i>null</i> otherwise nothing is done).
-	 * 
+	 *
+	 * <p><i>Note:
+	 * 	Remember that the destruction manager lets destroying automatically jobs
+	 * 	only when their destructionTime has been reached.
+	 * </i></p>
+	 *
+	 * @param newManager	Its new destruction manager (MUST be different from
+	 *                  	<i>null</i> otherwise nothing is done).
+	 *
 	 * @see DestructionManager#remove(UWSJob)
 	 * @see DestructionManager#update(UWSJob)
 	 */
@@ -280,7 +396,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the used execution manager.
-	 * 
+	 *
 	 * @return	The used execution manager.
 	 */
 	public final ExecutionManager getExecutionManager(){
@@ -294,12 +410,16 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * <p>Sets the execution manager to use.</p>
-	 * 
-	 * <p><i><u>note:</u> All jobs managed by the old execution manager are removed from it and added to the new manager.</i></p>
-	 * 
-	 * @param manager	The execution manager to use (MUST be different from <i>null</i> otherwise nothing is done).
-	 * 
+	 * Sets the execution manager to use.
+	 *
+	 * <p><i>Note:
+	 * 	All jobs managed by the old execution manager are removed from it and
+	 * 	added to the new manager.
+	 * </i></p>
+	 *
+	 * @param manager	The execution manager to use (MUST be different from
+	 *               	<i>null</i> otherwise nothing is done).
+	 *
 	 * @see ExecutionManager#remove(UWSJob)
 	 * @see ExecutionManager#execute(UWSJob)
 	 */
@@ -320,11 +440,36 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 		}
 	}
 
+	/**
+	 * Tell how this job list behaves when a job destruction is asked.
+	 *
+	 * @return	The job destruction policy of this job list.
+	 *
+	 * @since 4.3
+	 */
+	public final JobDestructionPolicy getDestroyPolicy(){
+		return destructionPolicy;
+	}
+
+	/**
+	 * Set how this job list must behave when a job destruction is asked.
+	 *
+	 * @param destroyPolicy	The job destruction policy to set.
+	 *                     	<i>If NULL, the default policy (i.e.
+	 *                     	{@link #DEFAULT_JOB_DESTRUCTION_POLICY}) will be
+	 *                     	set.</i>
+	 *
+	 * @since 4.3
+	 */
+	public final void setDestructionPolicy(JobDestructionPolicy destroyPolicy){
+		this.destructionPolicy = (destroyPolicy == null) ? DEFAULT_JOB_DESTRUCTION_POLICY : destroyPolicy;
+	}
+
 	/**
 	 * Gets the UWS URL of this jobs list in function of its UWS.
-	 * 
+	 *
 	 * @return	Its corresponding UWSUrl.
-	 * 
+	 *
 	 * @see UWSService#getUrlInterpreter()
 	 * @see UWSUrl#listJobs(String)
 	 */
@@ -337,7 +482,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the name of this jobs list.
-	 * 
+	 *
 	 * @return	JobList name.
 	 */
 	public final String getName(){
@@ -346,24 +491,29 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the job whose the ID is given in parameter.
-	 * 
+	 *
 	 * @param jobID	The ID of the job to get.
-	 * 
-	 * @return		The requested job or <i>null</i> if there is no job with the given ID.
+	 *
+	 * @return	The requested job or <i>null</i> if there is no job with the
+	 *        	given ID.
 	 */
 	public final UWSJob getJob(String jobID){
 		return jobsList.get(jobID);
 	}
 
 	/**
-	 * Gets the job whose the ID is given in parameter ONLY IF it is the one of the specified user OR IF the specified job is owned by an anonymous user.
-	 * 
-	 * @param jobID		ID of the job to get.
-	 * @param user		The user who asks this job (<i>null</i> means no particular owner => cf {@link #getJob(String)}).
-	 * 
-	 * @return			The requested job or <i>null</i> if there is no job with the given ID or if the user is not allowed to get the given job.
-	 * 
-	 * @throws UWSException	If the given user is not allowed to read the content of this jobs list or to read the specified job.
+	 * Gets the job whose the ID is given in parameter ONLY IF it is the one of
+	 * the specified user OR IF the specified job is owned by an anonymous user.
+	 *
+	 * @param jobID	ID of the job to get.
+	 * @param user	The user who asks this job (<i>null</i> means no particular
+	 *            	owner => cf {@link #getJob(String)}).
+	 *
+	 * @return	The requested job or <i>null</i> if there is no job with the
+	 *        	given ID or if the user is not allowed to get the given job.
+	 *
+	 * @throws UWSException	If the given user is not allowed to read the content
+	 *                     	of this jobs list or to read the specified job.
 	 */
 	public UWSJob getJob(String jobID, JobOwner user) throws UWSException{
 		if (user != null && !user.hasReadPermission(this))
@@ -384,9 +534,9 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets an iterator on the whole jobs list.
-	 * 
+	 *
 	 * @return 	All jobs of this list.
-	 * 
+	 *
 	 * @see #iterator()
 	 */
 	public final Iterator<UWSJob> getJobs(){
@@ -395,12 +545,14 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets an iterator on the jobs list of the specified user.
-	 * 
-	 * @param user 	The owner/user who asks for this operation (may be <i>null</i>).
-	 * 
-	 * @return 			An iterator on all jobs which have been created by the specified owner/user
-	 * 					or a NullIterator if the specified owner/user has no job
-	 * 					or an iterator on all the jobs if <i>ownerId</i> is <i>null</i>.
+	 *
+	 * @param user 	The owner/user who asks for this operation
+	 *            	(may be <i>null</i>).
+	 *
+	 * @return 	An iterator on all jobs which have been created by the specified
+	 *        	owner/user
+	 * 			or a NullIterator if the specified owner/user has no job
+	 * 			or an iterator on all the jobs if <i>ownerId</i> is <i>null</i>.
 	 */
 	public Iterator<UWSJob> getJobs(JobOwner user){
 		if (user == null)
@@ -430,7 +582,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets an iterator on the jobs list.
-	 * 
+	 *
 	 * @see java.lang.Iterable#iterator()
 	 */
 	@Override
@@ -440,7 +592,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the number of jobs into this list.
-	 * 
+	 *
 	 * @return	Number of jobs.
 	 */
 	public final int getNbJobs(){
@@ -449,9 +601,9 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the number of jobs owned by the given user into this list.
-	 * 
+	 *
 	 * @param user The owner/user (may be <i>null</i>).
-	 * 
+	 *
 	 * @return	Number of jobs that the given owner/user has,
 	 * 			or the number of all jobs if <i>user</i> is <i>null</i>.
 	 */
@@ -468,7 +620,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets all users that own at least one job in this list.
-	 * 
+	 *
 	 * @return	An iterator on owners.
 	 */
 	public final Iterator<JobOwner> getUsers(){
@@ -477,7 +629,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Gets the number of all users that have at least one job in this list.
-	 * 
+	 *
 	 * @return	The number of job owners.
 	 */
 	public final int getNbUsers(){
@@ -488,11 +640,12 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	/* JOB MANAGEMENT METHODS */
 	/* ********************** */
 	/**
-	 * Gets all job whose the runID is equals (not case sensitive) to the given runID.
-	 * 
+	 * Gets all job whose the runID is equals (not case sensitive) to the given
+	 * runID.
+	 *
 	 * @param runID	The runID of jobs to search.
-	 * 
-	 * @return		All the corresponding jobs.
+	 *
+	 * @return	All the corresponding jobs.
 	 */
 	public final List<UWSJob> searchJobs(String runID){
 		ArrayList<UWSJob> foundJobs = new ArrayList<UWSJob>();
@@ -508,15 +661,18 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * <p>Add the given job to the list except if a job with the same jobID already exists.
-	 * The jobs list of the new job's owner is always updated if the job has been added.</p>
-	 * 
-	 * @param j			The job to add.
-	 * 
-	 * @return	The JobID if the job has been successfully added, <i>null</i> otherwise.
-	 * 
-	 * @throws UWSException If the owner of the given job is not allowed to add any job into this jobs list.
-	 * 
+	 * Add the given job to the list except if a job with the same jobID already
+	 * exists. The jobs list of the new job's owner is always updated if the job
+	 * has been added.
+	 *
+	 * @param j	The job to add.
+	 *
+	 * @return	The JobID if the job has been successfully added,
+	 *        	<i>null</i> otherwise.
+	 *
+	 * @throws UWSException If the owner of the given job is not allowed to add
+	 *                     	any job into this jobs list.
+	 *
 	 * @see UWSJob#setJobList(JobList)
 	 * @see UWSService#getBackupManager()
 	 * @see UWSBackupManager#saveOwner(JobOwner)
@@ -566,12 +722,84 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * <p>Lets notifying the destruction manager of a possible modification of the destructionTime of the given job.</p>
-	 * 
-	 * <p><i><u>Note:</u> This method does nothing if this jobs list has no destruction manager, if the given job is NULL or if this jobs list does not know the given job.</i></p>
-	 * 
+	 * Archive the specified job.
+	 *
+	 * <p>
+	 * 	Resources (i.e. threads and files) of an archived jobs are destroyed.
+	 * 	Only the description is still available. The job can not be executed any
+	 * 	more. It is visible in the job list ONLY IF a filter on the
+	 * 	{@link ExecutionPhase#ARCHIVED ARCHIVED} phase is set.
+	 * </p>
+	 *
+	 * @param jobId	The ID of the job to archive.
+	 *
+	 * @return	<i>true</i> if it has been successfully archived,
+	 *        	<i>false</i> otherwise.
+	 *
+	 * @see UWSJob#archive()
+	 *
+	 * @since 4.3
+	 */
+	public boolean archiveJob(final String jobId){
+		UWSJob job = getJob(jobId);
+
+		if (job != null){
+			// Archive the job:
+			job.archive();
+
+			// Save the owner jobs list:
+			if (job.getOwner() != null && uws.getBackupManager() != null)
+				uws.getBackupManager().saveOwner(job.getOwner());
+
+			return true;
+		}else
+			return false;
+	}
+
+	/**
+	 * Archive the specified job if the given user is allowed to.
+	 *
+	 * <p>
+	 * 	Resources (i.e. threads and files) of an archived jobs are destroyed.
+	 * 	Only the description is still available. The job can not be executed any
+	 * 	more. It is visible in the job list ONLY IF a filter on the
+	 * 	{@link ExecutionPhase#ARCHIVED ARCHIVED} phase is set.
+	 * </p>
+	 *
+	 * @param jobId	The ID of the job to archive.
+	 * @param user	The user who asks to archive the specified job.
+	 *
+	 * @return	<i>true</i> if it has been successfully archived,
+	 *        	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If the given user is not allowed to update the
+	 *                     	content of this jobs list or of the specified job.
+	 *
+	 * @since 4.3
+	 */
+	public boolean archiveJob(final String jobId, final JobOwner user) throws UWSException{
+		if (user != null){
+			if (!user.hasWritePermission(this))
+				throw new UWSException(UWSException.PERMISSION_DENIED, UWSExceptionFactory.writePermissionDenied(user, true, getName()));
+			UWSJob job = getJob(jobId);
+			if (job != null && job.getOwner() != null && !user.equals(job.getOwner()) && !user.hasWritePermission(job))
+				throw new UWSException(UWSException.PERMISSION_DENIED, UWSExceptionFactory.writePermissionDenied(user, false, jobId));
+		}
+		return archiveJob(jobId);
+	}
+
+	/**
+	 * Lets notifying the destruction manager of a possible modification of the
+	 * destructionTime of the given job.
+	 *
+	 * <p><i>Note:
+	 * 	This method does nothing if this jobs list has no destruction manager,
+	 * 	if the given job is NULL or if this jobs list does not know the given
+	 * 	job.
+	 * </i></p>
+	 *
 	 * @param job	The job whose the destructionTime may have been modified.
-	 * 
+	 *
 	 * @see DestructionManager#update(UWSJob)
 	 */
 	public final void updateDestruction(UWSJob job){
@@ -580,12 +808,13 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * <p>Lets removing (NOT DESTROYING) the specified job from this jobs list.</p>
-	 * 
-	 * @param jobId		The ID of the job to remove.
-	 * 
-	 * @return			The removed job or <i>null</i> if there is no job with the given jobID.
-	 * 
+	 * Lets removing (NOT DESTROYING) the specified job from this jobs list.
+	 *
+	 * @param jobId	The ID of the job to remove.
+	 *
+	 * @return	The removed job
+	 *        	or <i>null</i> if there is no job with the given jobID.
+	 *
 	 * @see DestructionManager#remove(UWSJob)
 	 */
 	protected UWSJob removeJob(final String jobId){
@@ -610,49 +839,107 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 	}
 
 	/**
-	 * Removes the job from the list and deletes all its attached resources ({@link UWSJob#clearResources()}.
-	 * The jobs list of the new job's owner is always saved.
-	 * 
-	 * @param jobId		The ID of the job to destroy.
-	 * 
-	 * @return			<i>true</i> if it has been successfully destroyed, <i>false</i> otherwise.
-	 * 
+	 * Removes the job from the list and deletes all its attached resources
+	 * ({@link UWSJob#clearResources()}.
+	 *
+	 * <p><i>Note:
+	 * 	The jobs list of the destroyed job's owner is always updated.
+	 * </i></p>
+	 *
+	 * <p><i><b>Important note:</b>
+	 * 	This function will not destroy the job, but will archive it in the
+	 * 	following cases:
+	 * </i></p>
+	 * <ul>
+	 * 	<li><i>the {@link #getDestroyPolicy() destroy policy}
+	 * 	    is {@link JobDestructionPolicy#ALWAYS_ARCHIVE ALWAYS_ARCHIVE},</i></li>
+	 * 	<li><i>the {@link #getDestroyPolicy() destroy policy}
+	 * 	    is {@link JobDestructionPolicy#ARCHIVE_ON_DATE ARCHIVE_ON_DATE}
+	 * 	    and the destruction time has been reached,</i></li>
+	 * </ul>
+	 * <p><i>
+	 * 	In all the other cases but also if the job is already in
+	 * 	{@link ExecutionPhase#ARCHIVED ARCHIVED} phase, the specified job will
+	 * 	be destroyed.
+	 * </i></p>
+	 *
+	 * @param jobId	The ID of the job to destroy.
+	 *
+	 * @return	<i>true</i> if it has been successfully destroyed,
+	 *        	<i>false</i> otherwise.
+	 *
 	 * @see #removeJob(String)
 	 * @see UWSJob#clearResources()
 	 * @see UWSService#getBackupManager()
 	 * @see UWSBackupManager#saveOwner(JobOwner)
+	 * @see #archiveJob(String)
 	 */
 	public boolean destroyJob(final String jobId){
-		// Remove the job:
-		UWSJob destroyedJob = removeJob(jobId);
-
-		if (destroyedJob != null){
-			// Clear associated resources:
-			destroyedJob.clearResources();
-
-			// Save the owner jobs list:
-			if (destroyedJob.getOwner() != null && uws.getBackupManager() != null)
-				uws.getBackupManager().saveOwner(destroyedJob.getOwner());
-
-			// Log this job destruction:
-			getLogger().logJob(LogLevel.INFO, destroyedJob, "DESTROY", "The job \"" + destroyedJob.getJobId() + "\" has been removed from the job list \"" + name + "\".", null);
-
-			return true;
+		// Get the corresponding job and return immediately if none can be found:
+		UWSJob job = getJob(jobId);
+		if (job == null)
+			return false;
+
+		// Determine whether the destruction date is already reached or not:
+		boolean dateReached = job.getDestructionTime() != null && job.getDestructionTime().compareTo(new Date()) <= 0;
+
+		/* 3 policies are possible for a job destruction:
+		 *   a. ALWAYS_DELETE => whatever is the job destruction time or the job
+		 *                       phase, the job is immediately destroyed.
+		 *   b. ALWAYS_ARCHIVE => the job is always archived, EXCEPT if it is
+		 *                        already in ARCHIVED phase. In this last case,
+		 *                        it will be destroyed.
+		 *   c. ARCHIVE_ON_DATE => the job is archived ONLY IF the destruction
+		 *                         time is reached. Otherwise the job is
+		 *                         destroyed.
+		 *
+		 *  Which gives the 2 following cases: */
+
+		/* CASE 1: Destroy the job if in any of the following cases:
+		 *           - already ARCHIVED,
+		 *           - policy = ALWAYS_DELETE,
+		 *           - policy = ARCHIVE_ON_DATE and the destruction date is not
+		 *             yet reached. */
+		if (job.getPhase() == ExecutionPhase.ARCHIVED || destructionPolicy == JobDestructionPolicy.ALWAYS_DELETE || (destructionPolicy == JobDestructionPolicy.ARCHIVE_ON_DATE && !dateReached)){
+			// Remove the job:
+			UWSJob destroyedJob = removeJob(jobId);
+
+			if (destroyedJob != null){
+				// Clear associated resources:
+				destroyedJob.clearResources();
+
+				// Save the owner jobs list:
+				if (destroyedJob.getOwner() != null && uws.getBackupManager() != null)
+					uws.getBackupManager().saveOwner(destroyedJob.getOwner());
+
+				// Log this job destruction:
+				getLogger().logJob(LogLevel.INFO, destroyedJob, "DESTROY", "The job \"" + destroyedJob.getJobId() + "\" has been removed from the job list \"" + name + "\".", null);
+
+				return true;
+			}
+			return false;
 		}
-
-		return false;
+		/* CASE 2: Archive the job if not already ARCHIVED and if the policy is
+		 *         either ALWAYS_ARCHIVE or ARCHIVE_ON_DATE while the
+		 *         destruction date is reached: */
+		else
+			return archiveJob(jobId);
 	}
 
 	/**
-	 * Removes the job from the list and deletes all its attached resources ({@link UWSJob#clearResources()}.
-	 * The jobs list of the new job's owner is always saved.
-	 * 
-	 * @param jobId		The ID of the job to destroy.
-	 * @param user		The user who asks to destroy the specified job.
-	 * 
-	 * @return			<i>true</i> if it has been successfully destroyed, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If the given user is not allowed to update the content of this jobs list or to destroy the specified job.
+	 * Removes the job from the list and deletes all its attached resources
+	 * ({@link UWSJob#clearResources()}. The jobs list of the new job's owner is
+	 * always saved.
+	 *
+	 * @param jobId	The ID of the job to destroy.
+	 * @param user	The user who asks to destroy the specified job.
+	 *
+	 * @return	<i>true</i> if it has been successfully destroyed,
+	 *        	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If the given user is not allowed to update the
+	 *                     	content of this jobs list or to destroy the
+	 *                     	specified job.
 	 */
 	public boolean destroyJob(final String jobId, final JobOwner user) throws UWSException{
 		if (user != null){
@@ -667,7 +954,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/*
 	 * Removes all jobs of this list.
-	 * 
+	 *
 	 * @see #removeJob(String)
 	 *
 	public synchronized void removeAll(){
@@ -678,7 +965,7 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Destroys all jobs of this list.
-	 * 
+	 *
 	 * @see #destroyJob(String)
 	 */
 	public synchronized void clear(){
@@ -689,11 +976,12 @@ public class JobList extends SerializableUWSObject implements Iterable<UWSJob> {
 
 	/**
 	 * Destroys all jobs owned by the specified user.
-	 * 
+	 *
 	 * @param owner The owner/user who asks for this operation.
-	 * 
-	 * @throws UWSException	If the given user is not allowed to update of the content of this jobs list.
-	 * 
+	 *
+	 * @throws UWSException	If the given user is not allowed to update of the
+	 *                     	content of this jobs list.
+	 *
 	 * @see #clear()
 	 * @see #destroyJob(String)
 	 */
diff --git a/src/uws/job/JobPhase.java b/src/uws/job/JobPhase.java
index 01926e48a8241d896fc1397110b2ed07433eb65c..d8f08a491c2eaf0089819ad476e91eea7da07542 100644
--- a/src/uws/job/JobPhase.java
+++ b/src/uws/job/JobPhase.java
@@ -362,14 +362,16 @@ public class JobPhase implements Serializable {
 	 *
 	 * <p><i>Note:
 	 * 	By default, it returns TRUE only if the current phase is
-	 * 	{@link ExecutionPhase#EXECUTING EXECUTING}!
+	 * 	{@link ExecutionPhase#EXECUTING EXECUTING} or
+	 * 	{@link ExecutionPhase#SUSPENDED SUSPENDED} (since it is a phase that can
+	 * 	happen only during execution)!
 	 * </i></p>
 	 *
 	 * @return	<i>true</i> if the job is executing,
 	 *        	<i>false</i> otherwise.
 	 */
 	public boolean isExecuting(){
-		return phase == ExecutionPhase.EXECUTING;
+		return phase == ExecutionPhase.EXECUTING || phase == ExecutionPhase.SUSPENDED;
 	}
 
 	@Override
diff --git a/src/uws/job/UWSJob.java b/src/uws/job/UWSJob.java
index ddf5504dea4af6bf3c1dc2db6e768f60c7390f1b..84c68adf1c5fc1516c755d717d3ce0d3de50c5c3 100644
--- a/src/uws/job/UWSJob.java
+++ b/src/uws/job/UWSJob.java
@@ -38,6 +38,7 @@ import uws.UWSException;
 import uws.UWSExceptionFactory;
 import uws.UWSToolBox;
 import uws.job.jobInfo.JobInfo;
+import uws.job.jobInfo.SingleValueJobInfo;
 import uws.job.manager.ExecutionManager;
 import uws.job.parameters.UWSParameters;
 import uws.job.serializer.UWSSerializer;
@@ -1105,6 +1106,12 @@ public class UWSJob extends SerializableUWSObject {
 	 * job can be updated (considering its current execution phase, see
 	 * {@link JobPhase#isJobUpdatable()}).
 	 *
+	 * <p><i><b>Important note:</b>
+	 * 	If the given parameter value is an {@link UploadFile} and that it is
+	 * 	impossible to move it close to the job, this parameter will be removed.
+	 * 	No error is thrown, but a warning message is logged.
+	 * </i></p>
+	 *
 	 * @param paramName		The name of the parameter to add or to update.
 	 * @param paramValue	The (new) value of the specified parameter.
 	 *
@@ -1125,6 +1132,12 @@ public class UWSJob extends SerializableUWSObject {
 	 * job can be updated (considering its current execution phase, see
 	 * {@link JobPhase#isJobUpdatable()}).
 	 *
+	 * <p><i><b>Important note:</b>
+	 * 	If the given parameter value is an {@link UploadFile} and that it is
+	 * 	impossible to move it close to the job, this parameter will be removed.
+	 * 	No error is thrown, but a warning message is logged.
+	 * </i></p>
+	 *
 	 * @param paramName		The name of the parameter to add or to update.
 	 * @param paramValue	The (new) value of the specified parameter.
 	 * @param user			The user who asks for this update.
@@ -1145,19 +1158,21 @@ public class UWSJob extends SerializableUWSObject {
 			// Set the parameter:
 			inputParams.set(paramName, paramValue);
 
-			// If it is a file or an array containing files, they must be moved in a location related to this job:
-			try{
-				if (paramValue instanceof UploadFile)
-					((UploadFile)paramValue).move(this);
-				else if (paramValue.getClass().isArray()){
-					for(Object o : (Object[])paramValue){
-						if (o != null && o instanceof UploadFile)
-							((UploadFile)o).move(this);
+			// CASE DESTRUCTION_TIME: update the thread dedicated to the destruction:
+			if (paramValue.equals(PARAM_DESTRUCTION_TIME)){
+				if (myJobList != null)
+					myJobList.updateDestruction(this);
+			}
+			// DEFAULT: test whether the parameter is a file, and if yes, move it in a location related to this job:
+			else{
+				if (paramValue != null && paramValue instanceof UploadFile){
+					try{
+						((UploadFile)paramValue).move(this);
+					}catch(IOException ioe){
+						getLogger().logJob(LogLevel.WARNING, this, "MOVE_UPLOAD", "Can not move an uploaded file in the job \"" + jobId + "\"!", ioe);
+						inputParams.remove(paramName);
 					}
 				}
-			}catch(IOException ioe){
-				getLogger().logJob(LogLevel.WARNING, this, "MOVE_UPLOAD", "Can not move an uploaded file in the job \"" + jobId + "\"!", ioe);
-				return false;
 			}
 
 			// Apply the retrieved phase:
@@ -1190,6 +1205,12 @@ public class UWSJob extends SerializableUWSObject {
 	 * 		done.</li>
 	 * </ul>
 	 *
+	 * <p><i><b>Important note:</b>
+	 * 	If a given parameter value is an {@link UploadFile} and that it is
+	 * 	impossible to move it close to the job, this parameter will be removed.
+	 * 	No error is thrown, but a warning message is logged.
+	 * </i></p>
+	 *
 	 * @param params	A list of parameters to add/update.
 	 * @return	<i>true</i> if all the given parameters have been successfully
 	 *        	added/updated,
@@ -1236,6 +1257,12 @@ public class UWSJob extends SerializableUWSObject {
 	 * 		done.</li>
 	 * </ul></p>
 	 *
+	 * <p><i><b>Important note:</b>
+	 * 	If a given parameter value is an {@link UploadFile} and that it is
+	 * 	impossible to move it close to the job, this parameter will be removed.
+	 * 	No error is thrown, but a warning message is logged.
+	 * </i></p>
+	 *
 	 * @param params	The UWS parameters to update.
 	 * @param user		The user who asks for this update.
 	 *
@@ -1585,6 +1612,7 @@ public class UWSJob extends SerializableUWSObject {
 				throw new NullPointerException("Missing job work! The thread created by the factory is NULL => The job can't be executed!");
 
 			// Change the job phase:
+			setPhase(ExecutionPhase.QUEUED);
 			setPhase(ExecutionPhase.EXECUTING);
 
 			// Set the start time:
@@ -1796,19 +1824,93 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Stops the job if running, removes the job from the execution manager,
-	 * stops the timer for the execution duration and may clear all files or any
-	 * other resources associated to this job.
+	 * Archive this job.
+	 *
+	 * <p>
+	 * 	An archive job can not be executed any more. Threads, results and input
+	 * 	files are destroyed but the description and the error summary of
+	 * 	the job stay unchanged (except the execution phase which will then be
+	 * 	{@link ExecutionPhase#ARCHIVED ARCHIVED}).
+	 * </p>
 	 *
 	 * <p><i>Note:
-	 * 	By default the job is aborted, the {@link UWSJob#thread} attribute is
-	 * 	set to null, the timers are stopped and uploaded files, results and the
-	 * 	error summary are deleted and the jobInfo is destroyed.
+	 * 	The current phase is stored as job information (only if no JobInfo is
+	 * 	already set) in order to satisfy the user curiosity (i.e. "in what
+	 * 	phase was this job before being archived?").
 	 * </i></p>
+	 *
+	 * @return	<code>true</code> if this job has been successfully archived,
+	 *        	<code>false</code> otherwise.
+	 *
+	 * @throws UWSException	If any error occurs while clearing resources
+	 *                     	or changing the phase of this job.
+	 *
+	 * @since 4.3
+	 */
+	public boolean archive(){
+		/* Interrupt the corresponding thread
+		 * and remove results and input files attached to this job: */
+		clearResources(false);
+
+		// Ensure this job is no longer in the destruction manager:
+		if (getJobList() != null && getJobList().getDestructionManager() != null)
+			getJobList().getDestructionManager().remove(this);
+
+		// Change the phase:
+		try{
+			// store the current phase as additional JobInfo for user curiosity
+			//  (only if no JobInfo is already set):
+			if (getJobInfo() == null)
+				setJobInfo(new SingleValueJobInfo("oldPhase", getPhase().toString()));
+			// change phase:
+			setPhase(ExecutionPhase.ARCHIVED);
+			// log the success of the archiving operation:
+			getLogger().logJob(LogLevel.INFO, this, "ARCHIVE", "Job successfully archived!", null);
+			return true;
+		}catch(UWSException ue){
+			getLogger().logJob(LogLevel.ERROR, this, "ARCHIVE", "Impossible to change the phase of this job into ARCHIVED!", ue);
+			return false;
+		}
+	}
+
+	/**
+	 * Stops the job if running, removes the job from the execution manager,
+	 * stops the timer for the execution duration.
+	 *
+	 * <p>
+	 * 	Besides, ALL files AND ANY other resources (e.g. thread) associated with
+	 * 	this job are destroyed.
+	 * </p>
+	 *
+	 * @see #clearResources(boolean)
 	 */
 	public void clearResources(){
+		clearResources(true);
+	}
+
+	/**
+	 * Stops the job if running, removes the job from the execution manager,
+	 * stops the timer for the execution duration.
+	 *
+	 * <p>
+	 * 	Besides, resources (e.g. thread) associated with this job are freed.
+	 * 	Depending on the given parameter, all (<code>true</code>) or just input
+	 * 	and result files (<code>false</code>) are destroyed.
+	 * </p>
+	 *
+	 * @param fullClean	Indicate whether all resources or just some input and
+	 *                 	result files must be freed.
+	 *                  <code>true</code> to stop the job and delete everything
+	 *                  (input files, results, jobInfos and error summary),
+	 *                  or <code>false</code> to stop the job and delete only
+	 *                  all input files and results but not the jobInfos, the
+	 *                  error summary and the other parameters.
+	 *
+	 * @since 4.3
+	 */
+	public void clearResources(final boolean fullClean){
 		// If still running, abort/stop the job:
-		if (isRunning()){
+		if (!phase.isFinished()){
 			try{
 				abort();
 			}catch(UWSException e){
@@ -1829,40 +1931,54 @@ public class UWSJob extends SerializableUWSObject {
 		while(files.hasNext()){
 			upl = files.next();
 			try{
+				// delete the file:
 				upl.deleteFile();
+				// delete the internal reference to this input parameter:
+				files.remove();
 			}catch(IOException ioe){
 				getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to delete the file uploaded as parameter \"" + upl.paramName + "\" (" + upl.getLocation() + ") of the job \"" + jobId + "\"!", null);
 			}
 		}
 
 		// Clear all results file:
-		for(Result r : results.values()){
+		Iterator<Result> itResults = getResults();
+		Result r;
+		while(itResults.hasNext()){
+			r = itResults.next();
 			try{
+				// delete the file:
 				getFileManager().deleteResult(r, this);
+				// delete the internal reference to this result:
+				itResults.remove();
 			}catch(IOException ioe){
 				getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to delete the file associated with the result '" + r.getId() + "' of the job \"" + jobId + "\"!", ioe);
 			}
 		}
 
-		// Clear the error file:
-		if (errorSummary != null && errorSummary.hasDetail()){
-			try{
-				getFileManager().deleteError(errorSummary, this);
-			}catch(IOException ioe){
-				getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to delete the file associated with the error '" + errorSummary.message + "' of the job \"" + jobId + "\"!", ioe);
+		if (!fullClean){
+			// Clear the error file:
+			if (errorSummary != null && errorSummary.hasDetail()){
+				try{
+					// delete the file associated with the error details:
+					getFileManager().deleteError(errorSummary, this);
+					// delete the error summary:
+					errorSummary = null;
+				}catch(IOException ioe){
+					getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to delete the file associated with the error '" + errorSummary.message + "' of the job \"" + jobId + "\"!", ioe);
+				}
 			}
-		}
 
-		// Destroy the additional job info.:
-		if (jobInfo != null){
-			try{
-				jobInfo.destroy();
-			}catch(UWSException ue){
-				getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to destroy the additional information about the job \"" + jobId + "\"", ue);
+			// Destroy the additional job info.:
+			if (jobInfo != null){
+				try{
+					jobInfo.destroy();
+				}catch(UWSException ue){
+					getLogger().logJob(LogLevel.ERROR, this, "CLEAR_RESOURCES", "Impossible to destroy the additional information about the job \"" + jobId + "\"", ue);
+				}
 			}
 		}
 
-		getLogger().logJob(LogLevel.INFO, this, "CLEAR_RESOURCES", "Resources associated with the job \"" + getJobId() + "\" have been successfully freed.", null);
+		getLogger().logJob(LogLevel.INFO, this, "CLEAR_RESOURCES", (fullClean ? "All resources" : "Threads and input and result files") + " associated with the job \"" + getJobId() + "\" have been successfully freed.", null);
 	}
 
 	/* ******************* */
diff --git a/src/uws/job/manager/AbstractQueuedExecutionManager.java b/src/uws/job/manager/AbstractQueuedExecutionManager.java
index 41f84a8a8819db5d51a472f6c6ecaf50b522e6e3..ec8b10eb8f15868b71ec172dd61fa73e5fb4491d 100644
--- a/src/uws/job/manager/AbstractQueuedExecutionManager.java
+++ b/src/uws/job/manager/AbstractQueuedExecutionManager.java
@@ -2,21 +2,21 @@ package uws.job.manager;
 
 /*
  * 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)
  */
 
@@ -33,26 +33,30 @@ import uws.service.log.UWSLog;
 import uws.service.log.UWSLog.LogLevel;
 
 /**
- * <p>Abstract implementation of the interface {@link ExecutionManager} which lets managing an execution queue.</p>
- * 
+ * Abstract implementation of the interface {@link ExecutionManager} which lets
+ * managing an execution queue.
+ *
  * <p>
- * 	When calling {@link #execute(UWSJob)}, ALL jobs are put into the list of queued jobs (so their phase is changed
- * 	to {@link ExecutionPhase#QUEUED}). A call to {@link #refresh()}, reads this list and tries to execute the first job of the list.
- * 	The function {@link #isReadyForExecution(UWSJob)} decides whether the first job of the queue can be executed NOW or not.
+ * 	When calling {@link #execute(UWSJob)}, ALL jobs are put into the list of
+ * 	queued jobs (so their phase is changed to {@link ExecutionPhase#QUEUED}).
+ * 	A call to {@link #refresh()}, reads this list and tries to execute the first
+ * 	job of the list. The function {@link #isReadyForExecution(UWSJob)} decides
+ * 	whether the first job of the queue can be executed NOW or not.
  * </p>
- * 
+ *
  * <p><i>Note:
  * 	The order of queued jobs is preserved: it is implemented by a FIFO queue.
  * </i></p>
- * 
+ *
  * <p><i>Note:
- *	After a call to {@link #stopAll()}, this manager is still able to execute new jobs.
- *	Except if it was not possible to stop them properly, stopped jobs could be executed again by calling
- *	afterwards {@link #execute(UWSJob)} with these jobs in parameter.
+ *	After a call to {@link #stopAll()}, this manager is still able to execute
+ *	new jobs. Except if it was not possible to stop them properly, stopped jobs
+ *	could be executed again by calling afterwards {@link #execute(UWSJob)} with
+ *	these jobs in parameter.
  * </i></p>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (12/2014)
+ * @version 4.3 (09/2017)
  */
 public abstract class AbstractQueuedExecutionManager implements ExecutionManager {
 
@@ -101,20 +105,24 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 
 	/**
 	 * Tells whether there is a waiting queue.
-	 * 
-	 * @return	<i>true</i> if at least one job is into the queue, <i>false</i> otherwise.
+	 *
+	 * @return	<i>true</i> if at least one job is into the queue,
+	 *        	<i>false</i> otherwise.
 	 */
 	public boolean hasQueue(){
 		return !queuedJobs.isEmpty();
 	}
 
 	/**
-	 * Tells whether the given job can be executed NOW. In other words, in function
-	 * of the result of this function, the given job will be put in the queue or it will be executed.
-	 * 
+	 * Tells whether the given job can be executed NOW. In other words, in
+	 * function of the result of this function, the given job will be put in the
+	 * queue or it will be executed.
+	 *
 	 * @param 	jobToExecute
-	 * 
-	 * @return	<i>true</i> if the given job can be executed NOW (=&gt; it will be executed), <i>false</i> otherwise (=&gt; it will be put in the queue).
+	 *
+	 * @return	<i>true</i> if the given job can be executed NOW (=&gt; it will
+	 *        	be executed),
+	 *        	<i>false</i> otherwise (=&gt; it will be put in the queue).
 	 */
 	public abstract boolean isReadyForExecution(UWSJob jobToExecute);
 
@@ -122,21 +130,23 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 	/* EXECUTION MANAGEMENT METHODS */
 	/* **************************** */
 	/**
-	 * <p>Removes the first queued job(s) from the queue and executes it (them)
-	 * <b>ONLY IF</b> it (they) can be executed (see {@link #isReadyForExecution(UWSJob)}).</p>
-	 * 
+	 * Removes the first queued job(s) from the queue and executes it (them)
+	 * <b>ONLY IF</b> it (they) can be executed (see
+	 * {@link #isReadyForExecution(UWSJob)}).
+	 *
 	 * <p><i>Note:
 	 * 	Nothing is done if there is no queue.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note:
-	 * 	If any error occurs while refreshing this manager, it SHOULD be logged using the service logger.
+	 * 	If any error occurs while refreshing this manager, it SHOULD be logged
+	 * 	using the service logger.
 	 * </i></p>
-	 * 
+	 *
 	 * @see #hasQueue()
 	 * @see #isReadyForExecution(UWSJob)
 	 * @see #startJob(UWSJob)
-	 * 
+	 *
 	 * @see uws.job.manager.ExecutionManager#refresh()
 	 */
 	@Override
@@ -160,11 +170,11 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 	/**
 	 * Starts immediately the given job. This job is removed from the list of
 	 * queued jobs and added into the list of running jobs.
-	 * 
+	 *
 	 * @param jobToStartNow		The job to start.
-	 * 
+	 *
 	 * @throws UWSException		If there is an error while starting the job.
-	 * 
+	 *
 	 * @see UWSJob#start(boolean)
 	 */
 	protected void startJob(final UWSJob jobToStartNow) throws UWSException{
@@ -176,21 +186,26 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 	}
 
 	/**
-	 * <p>Refreshes this manager and then put the given job into the queue (if it is not already into it).</p>
-	 * 
+	 * Refreshes this manager and then put the given job into the queue (if
+	 * it is not already into it).
+	 *
 	 * <p><i>Note:
-	 * 	If any error occurs while executing the given job, it SHOULD be logged using the service logger.
+	 * 	If any error occurs while executing the given job, it SHOULD be logged
+	 * 	using the service logger.
 	 * </i></p>
-	 * 
+	 *
 	 * @param jobToExecute	The job to execute.
-	 * 
-	 * @return				The resulting execution phase of the given job ({@link ExecutionPhase#EXECUTING EXECUTING} or {@link ExecutionPhase#QUEUED QUEUED} or <i>null</i> if the given job is <i>null</i>).
-	 * 
+	 *
+	 * @return	The resulting execution phase of the given job
+	 *        	({@link ExecutionPhase#EXECUTING EXECUTING} or
+	 *        	{@link ExecutionPhase#QUEUED QUEUED}
+	 *        	or <i>null</i> if the given job is <i>null</i>).
+	 *
 	 * @see #refresh()
 	 * @see UWSJob#isRunning()
 	 * @see #isReadyForExecution(UWSJob)
 	 * @see UWSJob#setPhase(ExecutionPhase)
-	 * 
+	 *
 	 * @see uws.job.manager.ExecutionManager#execute(UWSJob)
 	 */
 	@Override
@@ -221,7 +236,12 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 					refresh();
 				}
 			}catch(UWSException ue){
+				// log the error:
 				logger.logJob(LogLevel.ERROR, jobToExecute, "QUEUE", "Can not set the job \"" + jobToExecute.getJobId() + "\" in the QUEUED phase!", ue);
+				// set the phase HELD (meaning it is impossible to set the job into a QUEUED phase):
+				try{
+					jobToExecute.setPhase(ExecutionPhase.HELD);
+				}catch(UWSException e){}
 			}
 		}
 
@@ -229,12 +249,14 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager
 	}
 
 	/**
-	 * <p>Removes the given job from the lists of queued and running jobs and then refreshes the manager.</p>
-	 * 
+	 * Removes the given job from the lists of queued and running jobs and
+	 * then refreshes the manager.
+	 *
 	 * <p><i>Note:
-	 * 	If any error occurs while removing a job from this manager, it SHOULD be logged using the service logger.
+	 * 	If any error occurs while removing a job from this manager, it SHOULD be
+	 * 	logged using the service logger.
 	 * </i></p>
-	 * 
+	 *
 	 * @see uws.job.manager.ExecutionManager#remove(uws.job.UWSJob)
 	 */
 	@Override
diff --git a/src/uws/job/manager/DefaultDestructionManager.java b/src/uws/job/manager/DefaultDestructionManager.java
index 8a0314c2129b75a7edafabd0d100c61f457b8544..dbb623618fad20c09596aa7adadbf99818f3b55c 100644
--- a/src/uws/job/manager/DefaultDestructionManager.java
+++ b/src/uws/job/manager/DefaultDestructionManager.java
@@ -2,21 +2,21 @@ package uws.job.manager;
 
 /*
  * 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)
  */
 
@@ -27,49 +27,58 @@ import java.util.Timer;
 import java.util.TimerTask;
 import java.util.TreeSet;
 
+import uws.job.ExecutionPhase;
 import uws.job.UWSJob;
 
 /**
+ * The default implementation of the {@link DestructionManager} interface. Its
+ * goal is to manage the automatic destruction any given jobs.
+ *
  * <p>
- * 	The default implementation of the {@link DestructionManager} interface.
- * 	Its goal is to manage the automatic destruction any given jobs.
+ *	Jobs can be added thanks to {@link #update(UWSJob)} and removed with
+ *	{@link #remove(UWSJob)}. All added jobs are stored in a {@link TreeSet}
+ *	which sorts them by ascending destruction time. The job which must be
+ *	destroyed in first is used to start a timer. This one will destroyed the job
+ *	once its destruction time is reached.
  * </p>
- * 
+ *
  * <p>
- *	Jobs can be added thanks to {@link #update(UWSJob)} and removed with {@link #remove(UWSJob)}.
- *	All added jobs are stored in a {@link TreeSet} which sorts them by ascending destruction time.
- *	The job which must be destroyed in first is used to start a timer.
- *	This one will destroyed the job once its destruction time is reached.
+ * 	The list of jobs to destroy is supposed to be updated each time the
+ * 	destruction time of a job is changed. This update works only if the job
+ * 	knows its jobs list ({@link UWSJob#getJobList()} != null) and its jobs list
+ * 	has a destruction manager.
  * </p>
- * 
- * <p>
- * 	The list of jobs to destroy is supposed to be updated each time the destruction time of a job is changed. This update works only if
- *  the job knows its jobs list ({@link UWSJob#getJobList()} != null) and its jobs list has a destruction manager.
- * </p>
- * 
+ *
  * <p><i>Note:
- * 	The {@link #stop()} function lets stop this manager to watch for destructions of job until {@link #refresh()} or
- * 	{@link #update(UWSJob)} or {@link #remove(UWSJob)} is called. When stopped, the inner timer is canceled and set
- * 	to NULL ; no more thread resources is used.
+ * 	The {@link #stop()} function lets stop this manager to watch for
+ * 	destructions of job until {@link #refresh()} or {@link #update(UWSJob)} or
+ * 	{@link #remove(UWSJob)} is called. When stopped, the inner timer is canceled
+ * 	and set to NULL ; no more thread resources is used.
  * </i></p>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (12/2014)
+ * @version 4.3 (09/2017)
  */
 public class DefaultDestructionManager implements DestructionManager {
 	private static final long serialVersionUID = 1L;
 
-	/** The list of jobs to destroy. Jobs are sorted by ascending destruction time thanks to {@link TimeComparator}.*/
+	/** The list of jobs to destroy. Jobs are sorted by ascending destruction
+	 * time thanks to {@link TimeComparator}.*/
 	protected final TreeSet<UWSJob> jobsToDestroy;
 
 	/** Timer for the job destruction time.
-	 * Once the date-time indicated by this timer is reached the job is destroyed and removed from the jobs list. */
+	 * <p>
+	 * 	Once the date-time indicated by this timer is reached the job is
+	 * 	destroyed and removed from the jobs list.
+	 * </p> */
 	protected transient Timer timDestruction = null;
 
-	/** The job currently planned for destruction. This job will be destroyed by the timer timDestruction. */
+	/** The job currently planned for destruction. This job will be destroyed by
+	 * the timer timDestruction. */
 	protected UWSJob currentJob = null;
 
-	/** The date used by the timer to trigger the destruction of {@link #currentJob}. */
+	/** The date used by the timer to trigger the destruction of
+	 * {@link #currentJob}. */
 	protected Date currentDate = null;
 
 	/* *********** */
@@ -77,8 +86,12 @@ public class DefaultDestructionManager implements DestructionManager {
 	/* *********** */
 	/**
 	 * Builds the default destruction manager.
-	 * The list of jobs to destroy is initialized so that sorting jobs by ascending destruction time.
-	 * 
+	 *
+	 * <p>
+	 * 	The list of jobs to destroy is initialized so that sorting jobs by
+	 * 	ascending destruction time.
+	 * </p>
+	 *
 	 * @see TimeComparator
 	 */
 	public DefaultDestructionManager(){
@@ -89,7 +102,8 @@ public class DefaultDestructionManager implements DestructionManager {
 	/* TOOL METHODS */
 	/* ************ */
 	/**
-	 * Stops the timer if running and set to <i>null</i> {@link #timDestruction}, {@link #currentDate} and {@link #currentJob}.
+	 * Stops the timer if running, and sets {@link #timDestruction},
+	 * {@link #currentDate} and {@link #currentJob} to <i>null</i>.
 	 */
 	@Override
 	public synchronized final void stop(){
@@ -101,24 +115,24 @@ public class DefaultDestructionManager implements DestructionManager {
 	}
 
 	/**
-	 * Merely destroys the given job (if not <i>null</i>).
-	 * 
+	 * Merely destroys the given job
+	 * (if not NULL and not {@link ExecutionPhase#ARCHIVED ARCHIVED}).
+	 *
 	 * @param job	The job to destroy.
-	 * 
+	 *
 	 * @see UWSJob#getJobList()
 	 * @see uws.job.JobList#destroyJob(String)
 	 */
 	protected final void destroyJob(UWSJob job){
-		if (job != null && job.getJobList() != null){
+		if (job != null && job.getJobList() != null && job.getPhase() != ExecutionPhase.ARCHIVED)
 			job.getJobList().destroyJob(job.getJobId());
-		}
 	}
 
 	/* ***************** */
 	/* INHERITED METHODS */
 	/* ***************** */
 	/**
-	 * <p>Returns <i>true</i> if {@link #currentDate} is different from <i>null</i>.</p>
+	 * Returns <code>true</code> if {@link #currentDate} is different from NULL.
 	 */
 	@Override
 	public final boolean isRunning(){
@@ -145,17 +159,22 @@ public class DefaultDestructionManager implements DestructionManager {
 	 * 	<li>First, check the currently planned job:
 	 * 		<ul>
 	 * 			<li>if {@link #currentDate} is past, the timer is stopped.</li>
-	 * 			<li>else if another job must be destroyed before the current one or if the destruction time of the current job has been changed, the timer is stopped and the job is re-added into the list of jobs to destroy.</li>
+	 * 			<li>else if another job must be destroyed before the current one
+	 * 				or if the destruction time of the current job has been
+	 * 				changed, the timer is stopped and the job is re-added into
+	 * 				the list of jobs to destroy.</li>
 	 * 		</ul>
 	 * 	</li>
 	 * 	<li>Then, only if there is no currently planned job:
 	 * 		<ul>
-	 * 			<li>Clean the list of jobs to destroy (jobs which are supposed to be destroyed are destroyed and the others are only removed from this manager).</li>
+	 * 			<li>Clean the list of jobs to destroy (jobs which are supposed
+	 * 				to be destroyed are destroyed and the others are only
+	 * 				removed from this manager).</li>
 	 * 			<li>Restart the timer with the first job to destroy.</li>
 	 * 		</ul>
 	 * 	</li>
 	 * </ol>
-	 * 
+	 *
 	 * @see uws.job.manager.DestructionManager#refresh()
 	 * @see #stop()
 	 * @see #destroyJob(UWSJob)
@@ -165,9 +184,14 @@ public class DefaultDestructionManager implements DestructionManager {
 		// Finish the current timer if...
 		if (isRunning()){
 			// ...the time is elapsed:
-			if (currentDate.before(new Date()))
+			if (currentDate.before(new Date())){
 				stop();
-
+			}
+			// ...the job is already archived:
+			else if (currentJob.getPhase() == ExecutionPhase.ARCHIVED){
+				stop();
+				jobsToDestroy.remove(currentJob);
+			}
 			// ...the running timer is deprecated:
 			else if (!currentJob.getDestructionTime().equals(currentDate) || (!jobsToDestroy.isEmpty() && currentDate.after(jobsToDestroy.first().getDestructionTime()))){
 				jobsToDestroy.add(currentJob);
@@ -179,8 +203,10 @@ public class DefaultDestructionManager implements DestructionManager {
 		if (!isRunning()){
 			// get the next job on which a timer can be put:
 			currentJob = jobsToDestroy.pollFirst();
-			while(!jobsToDestroy.isEmpty() && (currentJob == null || currentJob.getDestructionTime() == null || currentJob.getDestructionTime().before(new Date()))){
-				if (currentJob.getDestructionTime() != null)
+			while(!jobsToDestroy.isEmpty() && (currentJob == null || currentJob.getPhase() == ExecutionPhase.ARCHIVED || currentJob.getDestructionTime() == null || currentJob.getDestructionTime().before(new Date()))){
+				if (currentJob.getPhase() == ExecutionPhase.ARCHIVED)
+					jobsToDestroy.remove(currentJob);
+				else if (currentJob.getDestructionTime() != null)
 					destroyJob(currentJob);
 				currentJob = jobsToDestroy.pollFirst();
 			}
@@ -199,20 +225,23 @@ public class DefaultDestructionManager implements DestructionManager {
 	}
 
 	/**
-	 * This function does something only if the given job knows its jobs list and has a valid destruction time.
-	 * Then there are two cases:
+	 * This function does something only if the given job knows its jobs list
+	 * and has a valid destruction time. Then there are two cases:
 	 * <ol>
-	 * 	<li><u>The destruction time of the given job is past:</u> the job is destroyed (see {@link #destroyJob(UWSJob)}).</li>
-	 * 	<li><u>Otherwise:</u> the job is removed and then added to the list of jobs to destroy. Finally this manager is refreshed (see {@link #refresh()}).</li>
+	 * 	<li><u>The destruction time of the given job is past:</u> the job is
+	 * 		destroyed (see {@link #destroyJob(UWSJob)}).</li>
+	 * 	<li><u>Otherwise:</u> the job is removed and then added to the list of
+	 * 		jobs to destroy. Finally this manager is refreshed (see
+	 * 		{@link #refresh()}).</li>
 	 * </ol>
-	 * 
+	 *
 	 * @see uws.job.manager.DestructionManager#update(uws.job.UWSJob)
 	 * @see #destroyJob(UWSJob)
 	 * @see #refresh()
 	 */
 	@Override
 	public synchronized void update(UWSJob job){
-		if (job != null && job.getJobList() != null && job.getDestructionTime() != null){
+		if (job != null && job.getJobList() != null && job.getDestructionTime() != null && job.getPhase() != ExecutionPhase.ARCHIVED){
 			if (job.getDestructionTime().before(new Date()))
 				destroyJob(job);
 			else{
@@ -225,9 +254,10 @@ public class DefaultDestructionManager implements DestructionManager {
 	}
 
 	/**
-	 * Merely removes the given job from the list of jobs to destroyed.
-	 * However if the given job is the currently planned job, the timer is stopped and the manager is refreshed.
-	 * 
+	 * Merely removes the given job from the list of jobs to destroyed. However
+	 * if the given job is the currently planned job, the timer is stopped and
+	 * the manager is refreshed.
+	 *
 	 * @see uws.job.manager.DestructionManager#remove(uws.job.UWSJob)
 	 * @see	#stop()
 	 * @see #refresh()
@@ -248,9 +278,9 @@ public class DefaultDestructionManager implements DestructionManager {
 	/* JOB COMPARATOR */
 	/* ************** */
 	/**
-	 * Lets a TreeSet or a TreeMap sorting {@link UWSJob} instances in an ascending order
-	 * and according to their destruction time.
-	 * 
+	 * Lets a TreeSet or a TreeMap sorting {@link UWSJob} instances in an
+	 * ascending order and according to their destruction time.
+	 *
 	 * @author Gr&eacute;gory Mantelet (CDS)
 	 * @version 05/2012
 	 */
@@ -262,7 +292,8 @@ public class DefaultDestructionManager implements DestructionManager {
 			if (job1 == null && job2 == null)
 				return 0;
 
-			Date date1 = job1.getDestructionTime(), date2 = job2.getDestructionTime();
+			Date date1 = job1.getDestructionTime(),
+					date2 = job2.getDestructionTime();
 
 			if (date1 == null && date2 == null)
 				return 0;
diff --git a/src/uws/service/log/UWSLog.java b/src/uws/service/log/UWSLog.java
index 0448234a6ae0ec0b8acb8afab17377cfda4d1afd..afee11846c52848c076da172f05f6203b9df97f6 100644
--- a/src/uws/service/log/UWSLog.java
+++ b/src/uws/service/log/UWSLog.java
@@ -1,50 +1,50 @@
 package uws.service.log;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import uws.job.ErrorSummary;
-import uws.job.JobList;
-import uws.job.Result;
-import uws.job.UWSJob;
-import uws.job.user.JobOwner;
-import uws.service.UWS;
-import uws.service.UWSUrl;
-
 /*
  * 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)
  */
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import uws.job.ErrorSummary;
+import uws.job.JobList;
+import uws.job.Result;
+import uws.job.UWSJob;
+import uws.job.user.JobOwner;
+import uws.service.UWS;
+import uws.service.UWSUrl;
+
 /**
  * Let log any kind of message about a UWS service.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (12/2014)
+ * @version 4.3 (09/2017)
  */
 public interface UWSLog {
 
 	/**
 	 * Indicate the level of the error: debug, info, warning or error.
-	 * 
+	 *
 	 * @author Gr&eacute;gory Mantelet (ARI)
 	 * @version 4.1 (09/2014)
 	 * @since 4.1
@@ -58,107 +58,120 @@ public interface UWSLog {
 	/* *********************** */
 
 	/**
-	 * <p>Generic way to log a message and/or an exception.</p>
-	 * 
+	 * Generic way to log a message and/or an exception.
+	 *
 	 * <p><i>Note:
-	 * 	The other functions of this class or extension, MAY be equivalent to a call to this function with some specific parameter values.
-	 * 	It should be especially the case for the debug(...), info(...), warning(...) and error(...) functions.
+	 * 	The other functions of this class or extension, MAY be equivalent to a
+	 * 	call to this function with some specific parameter values. It should be
+	 * 	especially the case for the debug(...), info(...), warning(...) and
+	 * 	error(...) functions.
 	 * </i></p>
-	 * 
-	 * @param level		Level of the error (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
-	 * @param context	Context of the log item (HTTP, Thread, Job, UWS, ...). <i>MAY be NULL</i>
+	 *
+	 * @param level		Level of the error (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
+	 * @param context	Context of the log item (HTTP, Thread, Job, UWS, ...).
+	 *               	<i>MAY be NULL</i>
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void log(final LogLevel level, final String context, final String message, final Throwable error);
 
 	/**
-	 * <p>Logs a debug message.</p>
-	 * 
+	 * Logs a debug message.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.WARNING, null, msg, null).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.WARNING, null, msg, null)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	A DEBUG message.
 	 */
 	public void debug(final String msg);
 
 	/**
-	 * <p>Logs an exception as a debug message.</p>
-	 * 
+	 * Logs an exception as a debug message.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.WARNING, null, null, t).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.WARNING, null, null, t)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param t	An exception.
 	 */
 	public void debug(final Throwable t);
 
 	/**
-	 * <p>Logs a full (message+exception) debug message.</p>
-	 * 
+	 * Logs a full (message+exception) debug message.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.WARNING, null, msg, t).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.WARNING, null, msg, t)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	A DEBUG message.
 	 * @param t		An exception.
 	 */
 	public void debug(final String msg, final Throwable t);
 
 	/**
-	 * <p>Logs the given information.</p>
-	 * 
+	 * Logs the given information.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.INFO, null, msg, null).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.INFO, null, msg, null)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	An INFO message.
 	 */
 	public void info(final String msg);
 
 	/**
-	 * <p>Logs the given warning.</p>
-	 * 
+	 * Logs the given warning.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.WARNING, null, msg, null).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.WARNING, null, msg, null)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	A WARNING message.
 	 */
 	public void warning(final String msg);
 
 	/**
-	 * <p>Logs the given error.</p>
-	 * 
+	 * Logs the given error.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.ERROR, null, msg, null).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.ERROR, null, msg, null)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	An ERROR message.
 	 */
 	public void error(final String msg);
 
 	/**
-	 * <p>Logs the given exception as an error.</p>
-	 * 
+	 * Logs the given exception as an error.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.ERROR, null, null, t).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.ERROR, null, null, t)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param t	An exception.
 	 */
 	public void error(final Throwable t);
 
 	/**
-	 * <p>Logs a full (message+exception) error message.</p>
-	 * 
+	 * Logs a full (message+exception) error message.
+	 *
 	 * <p><i>Note:
-	 * 	This function should be equals to: log(LogLevel.ERROR, null, msg, t).
+	 * 	This function should be equals to:
+	 * 		<code>log(LogLevel.ERROR, null, msg, t)</code>
 	 * </i></p>
-	 * 
+	 *
 	 * @param msg	An ERROR message.
 	 * @param t		An exception.
 	 */
@@ -169,89 +182,115 @@ public interface UWSLog {
 	/* ****************** */
 
 	/**
-	 * <p>Log a message and/or an error in the general context of UWS.</p>
-	 * 
+	 * Log a message and/or an error in the general context of UWS.
+	 *
 	 * <p>
-	 * 	One of the parameter is of type {@link Object}. This object can be used to provide more information to the log function
-	 * 	in order to describe as much as possible the state and/or result event.
+	 * 	One of the parameter is of type {@link Object}. This object can be used
+	 * 	to provide more information to the log function in order to describe as
+	 * 	much as possible the state and/or result event.
 	 * </p>
-	 * 
+	 *
 	 * <p>List of all events sent by the library (case sensitive):</p>
 	 * <ul>
-	 * 	<li>INIT (with "obj" as an instance of {@link UWS} except in case of error where "obj" is NULL)</li>
+	 * 	<li>INIT (with "obj" as an instance of {@link UWS} except in case of
+	 * 		error where "obj" is NULL)</li>
 	 * 	<li>ADD_JOB_LIST (with "obj" as an instance of {@link JobList})</li>
 	 * 	<li>DESTROY_JOB_LIST (with "obj" as an instance of {@link JobList})</li>
 	 * 	<li>DESTROY_JOB (with "obj" as an instance of {@link UWSUrl})</li>
 	 * 	<li>SERIALIZE (with "obj" as an instance of {@link UWSUrl})</li>
-	 * 	<li>SET_PARAM (with "obj" as an instance of {@link HttpServletRequest} in case of error)</li>
+	 * 	<li>SET_PARAM (with "obj" as an instance of {@link HttpServletRequest}
+	 * 		in case of error)</li>
 	 * 	<li>GET_RESULT (with "obj" as an instance of {@link Result})</li>
 	 * 	<li>GET_ERROR (with "obj" as an instance of {@link ErrorSummary})</li>
-	 * 	<li>RESTORATION (with "obj" the raw object to de-serialize (may be {@link JSONObject} or {@link JSONArray} or NULL))</li>
-	 * 	<li>BACKUP (with "obj" the object to backup ; may be {@link JobOwner}, a {@link UWSJob}, ...)</li>
-	 * 	<li>RESTORED (with "obj" as an integer array of 4 items: nb of restored jobs, total nb of jobs, nb of restored users, total nb of users)</li>
-	 * 	<li>BACKUPED (with "obj" as an integer array of 4 items: nb of saved jobs, total nb of jobs, nb of saved users, total nb of users or with just 2 items (the two last ones))</li>
+	 * 	<li>RESTORATION (with "obj" the raw object to de-serialize (may be
+	 * 		{@link JSONObject} or {@link JSONArray} or NULL))</li>
+	 * 	<li>BACKUP (with "obj" the object to backup ; may be {@link JobOwner},
+	 * 		a {@link UWSJob}, ...)</li>
+	 * 	<li>RESTORED (with "obj" as an integer array of 4 items: nb of restored
+	 * 		jobs, total nb of jobs, nb of restored users, total nb of users)</li>
+	 * 	<li>BACKUPED (with "obj" as an integer array of 4 items: nb of saved
+	 * 		jobs, total nb of jobs, nb of saved users, total nb of users or with
+	 * 		just 2 items (the two last ones))</li>
 	 * 	<li>FORMAT_ERROR (with a NULL "obj")</li>
 	 * 	<li>STOP (with "obj" as an instance of {@link UWS})</li>
 	 * </ul>
-	 * 
-	 * @param level		Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
-	 * @param obj		Object providing more information about the event/object at the origin of this log. <i>MAY be NULL</i>
-	 * @param event		Event at the origin of this log or action currently executed by UWS while this log is sent. <i>MAY be NULL</i>
+	 *
+	 * @param level		Level of the log (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
+	 * @param obj		Object providing more information about the event/object
+	 *           		at the origin of this log. <i>MAY be NULL</i>
+	 * @param event		Event at the origin of this log or action currently
+	 *             		executed by UWS while this log is sent.
+	 *             		<i>MAY be NULL</i>
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void logUWS(final LogLevel level, final Object obj, final String event, final String message, final Throwable error);
 
 	/**
-	 * <p>Log a message and/or an error in the HTTP context.
-	 * This log function is called when a request is received by the service. Consequently, the event is: REQUEST_RECEIVED.</p>
-	 * 
+	 * Log a message and/or an error in the HTTP context.
+	 * This log function is called when a request is received by the service.
+	 * Consequently, the event is: REQUEST_RECEIVED.
+	 *
 	 * <p><i>Note:
-	 * 	When a request is received, this function is called, and then, when the response has been written and sent to the client,
-	 * 	{@link #logHttp(LogLevel, HttpServletResponse, String, JobOwner, String, Throwable)} should be called.
-	 * 	These functions should always work together.
+	 * 	When a request is received, this function is called, and then, when the
+	 * 	response has been written and sent to the client,
+	 * 	{@link #logHttp(LogLevel, HttpServletResponse, String, JobOwner, String, Throwable)}
+	 * 	should be called. These functions should always work together.
 	 * </i></p>
-	 * 
-	 * @param level		Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
-	 * @param request	HTTP request received by the service. <i>SHOULD NOT be NULL</i>
-	 * @param requestId	ID to use to identify this request until its response is sent.
+	 *
+	 * @param level		Level of the log (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
+	 * @param request	HTTP request received by the service.
+	 *               	<i>SHOULD NOT be NULL</i>
+	 * @param requestId	ID to use to identify this request until its response is
+	 *                 	sent.
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @see #logHttp(LogLevel, HttpServletResponse, String, JobOwner, String, Throwable)
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void logHttp(final LogLevel level, final HttpServletRequest request, final String requestId, final String message, final Throwable error);
 
 	/**
-	 * <p>Log a message and/or an error in the HTTP context.
-	 * This log function is called when a response is sent to the client by the service. Consequently, the event is: RESPONSE_SENT.</p>
-	 * 
+	 * Log a message and/or an error in the HTTP context.
+	 * This log function is called when a response is sent to the client by the
+	 * service. Consequently, the event is: RESPONSE_SENT.
+	 *
 	 * <p><i>Note:
-	 * 	When a request is received, {@link #logHttp(LogLevel, HttpServletRequest, String, String, Throwable)} is called, and then,
-	 * 	when the response has been written and sent to the client, this function should be called.
-	 * 	These functions should always work together.
+	 * 	When a request is received, {@link #logHttp(LogLevel, HttpServletRequest, String, String, Throwable)}
+	 * 	is called, and then, when the response has been written and sent to the
+	 * 	client, this function should be called. These functions should always
+	 * 	work together.
 	 * </i></p>
-	 * 
-	 * @param level		Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
-	 * @param response	HTTP response sent by the service to the client. <i>MAY be NULL if an error occurs while writing the response</i>
-	 * @param requestId	ID to use to identify the request to which the given response is answering.
+	 *
+	 * @param level		Level of the log (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
+	 * @param response	HTTP response sent by the service to the client.
+	 *                	<i>MAY be NULL if an error occurs while writing the
+	 *                	response</i>
+	 * @param requestId	ID to use to identify the request to which the given
+	 *                 	response is answering.
 	 * @param user		Identified user which has sent the received request.
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @see #logHttp(LogLevel, HttpServletRequest, String, String, Throwable)
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void logHttp(final LogLevel level, final HttpServletResponse response, final String requestId, final JobOwner user, final String message, final Throwable error);
 
 	/**
-	 * <p>Log a message and/or an error in the JOB context.</p>
-	 * 
+	 * Log a message and/or an error in the JOB context.
+	 *
 	 * <p>List of all events sent by the library (case sensitive):</p>
 	 * <ul>
 	 * 	<li>CREATED</li>
@@ -259,6 +298,7 @@ public interface UWSLog {
 	 * 	<li>START</li>
 	 * 	<li>ABORT</li>
 	 * 	<li>ERROR</li>
+	 * 	<li>ARCHIVE</li>
 	 * 	<li>EXECUTING</li>
 	 * 	<li>CHANGE_PHASE</li>
 	 * 	<li>NOTIFY</li>
@@ -271,33 +311,40 @@ public interface UWSLog {
 	 * 	<li>CLEAR_RESOURCES</li>
 	 * 	<li>DESTROY</li>
 	 * </ul>
-	 * 
-	 * @param level		Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
+	 *
+	 * @param level		Level of the log (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
 	 * @param job		Job from which this log comes. <i>MAY be NULL</i>
-	 * @param event		Event at the origin of this log or action executed by the given job while this log is sent. <i>MAY be NULL</i>
+	 * @param event		Event at the origin of this log or action executed by
+	 *             		the given job while this log is sent. <i>MAY be NULL</i>
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void logJob(final LogLevel level, final UWSJob job, final String event, final String message, final Throwable error);
 
 	/**
 	 * <p>Log a message and/or an error in the THREAD context.</p>
-	 * 
+	 *
 	 * <p>List of all events sent by the library (case sensitive):</p>
 	 * <ul>
 	 * 	<li>START</li>
 	 * 	<li>SET_ERROR</li>
 	 * 	<li>END</li>
 	 * </ul>
-	 * 
-	 * @param level		Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i>
+	 *
+	 * @param level		Level of the log (info, warning, error, ...).
+	 *             		<i>SHOULD NOT be NULL, but if NULL anyway, the level
+	 *             		SHOULD be considered as INFO</i>
 	 * @param thread	Thread from which this log comes. <i>MAY be NULL</i>
-	 * @param event		Event at the origin of this log or action currently executed by the given thread while this log is sent. <i>MAY be NULL</i>
+	 * @param event		Event at the origin of this log or action currently
+	 *             		executed by the given thread while this log is sent.
+	 *             		<i>MAY be NULL</i>
 	 * @param message	Message to log. <i>MAY be NULL</i>
 	 * @param error		Error/Exception to log. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public void logThread(final LogLevel level, final Thread thread, final String event, final String message, final Throwable error);
diff --git a/test/uws/job/TestJobPhase.java b/test/uws/job/TestJobPhase.java
index f275d754999d5584fdb4806ba06d2421fa6f1fad..64b3c60951b85b4f1a56334435140c08d417b2a6 100644
--- a/test/uws/job/TestJobPhase.java
+++ b/test/uws/job/TestJobPhase.java
@@ -633,11 +633,17 @@ public class TestJobPhase {
 			for(ExecutionPhase phase : ExecutionPhase.values()){
 				// set the phase to test:
 				jobPhase.setPhase(phase, true);
-				// ensure isExecuting(...) returns TRUE only for EXECUTING:
-				if (phase == ExecutionPhase.EXECUTING)
-					assertTrue(jobPhase.isExecuting());
-				else
-					assertFalse(jobPhase.isExecuting());
+				// ensure isExecuting(...) returns TRUE only for EXECUTING
+				// or SUSPENDED:
+				switch(phase){
+					case EXECUTING:
+					case SUSPENDED:
+						assertTrue(jobPhase.isExecuting());
+						break;
+					default:
+						assertFalse(jobPhase.isExecuting());
+						break;
+				}
 			}
 		}catch(Exception ex){
 			ex.printStackTrace();