Skip to content
Snippets Groups Projects
Commit 3f6a3a28 authored by Grégory Mantelet's avatar Grégory Mantelet
Browse files

[UWS] Replace the public static variable for the tmp directory by a class

attribute.

In this way, it is possible to run two different instances of a UWS/TAP service
with a different temporary directory in the same JVM.
parent 3d22e42a
No related branches found
No related tags found
No related merge requests found
...@@ -16,7 +16,7 @@ package uws.service.file; ...@@ -16,7 +16,7 @@ package uws.service.file;
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>. * along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI) * Astronomisches Rechen Institut (ARI)
*/ */
...@@ -53,26 +53,31 @@ import uws.service.log.UWSLog.LogLevel; ...@@ -53,26 +53,31 @@ import uws.service.log.UWSLog.LogLevel;
import uws.service.request.UploadFile; import uws.service.request.UploadFile;
/** /**
* <p>All UWS files are stored in the local machine into the specified directory.</p> * All UWS files are stored in the local machine into the specified directory.
* *
* <p> * <p>
* The name of the log file, the result files and the backup files may be customized by overriding the following functions: * The name of the log file, the result files and the backup files may be
* {@link #getLogFileName(uws.service.log.UWSLog.LogLevel, String)}, {@link #getResultFileName(Result, UWSJob)}, {@link #getBackupFileName(JobOwner)} and {@link #getBackupFileName()}. * customised by overriding the following functions:
* {@link #getLogFileName(uws.service.log.UWSLog.LogLevel, String)},
* {@link #getResultFileName(Result, UWSJob)},
* {@link #getBackupFileName(JobOwner)} and {@link #getBackupFileName()}.
* </p> * </p>
* *
* <p> * <p>
* By default, results and backups are grouped by owner/user and owners/users are grouped thanks to {@link DefaultOwnerGroupIdentifier}. * By default, results and backups are grouped by owner/user and owners/users
* By using the appropriate constructor, you can change these default behaviors. * are grouped thanks to {@link DefaultOwnerGroupIdentifier}. By using the
* appropriate constructor, you can change these default behaviours.
* </p> * </p>
* *
* <p> * <p>
* A log file rotation is set by default so that avoiding a too big log file after several months/years of use. * A log file rotation is set by default so that avoiding a too big log file
* By default the rotation is done every month on the 1st at 6am. This frequency can be changed easily thanks to the function * after several months/years of use. By default the rotation is done every
* {@link #setLogRotationFreq(String)}. * month on the 1st at 6am. This frequency can be changed easily thanks to the
* function {@link #setLogRotationFreq(String)}.
* </p> * </p>
* *
* @author Gr&eacute;gory Mantelet (CDS;ARI) * @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 4.4 (07/2018) * @version 4.4 (08/2018)
*/ */
public class LocalUWSFileManager implements UWSFileManager { public class LocalUWSFileManager implements UWSFileManager {
...@@ -87,6 +92,10 @@ public class LocalUWSFileManager implements UWSFileManager { ...@@ -87,6 +92,10 @@ public class LocalUWSFileManager implements UWSFileManager {
/** Directory in which all files managed by this class will be written and read. */ /** Directory in which all files managed by this class will be written and read. */
protected final File rootDirectory; protected final File rootDirectory;
/** Directory in which temporary files (e.g. uploads) should be stored.
* @since 4.4 */
protected File tmpDirectory = new File(System.getProperty("java.io.tmpdir"));
/** Output toward the service log file. */ /** Output toward the service log file. */
protected PrintWriter logOutput = null; protected PrintWriter logOutput = null;
/** Frequency at which the log file must be "rotated" (the file is renamed with the date of its first write and a new log file is created). /** Frequency at which the log file must be "rotated" (the file is renamed with the date of its first write and a new log file is created).
...@@ -439,6 +448,21 @@ public class LocalUWSFileManager implements UWSFileManager { ...@@ -439,6 +448,21 @@ public class LocalUWSFileManager implements UWSFileManager {
return new File(upload.getLocation()); return new File(upload.getLocation());
} }
@Override
public File getTmpDirectory(){
return tmpDirectory;
}
@Override
public boolean setTmpDirectory(final File newTmpDir){
if (newTmpDir == null || !newTmpDir.exists() || !newTmpDir.isDirectory() || !newTmpDir.canRead() || !newTmpDir.canWrite())
return false;
else{
tmpDirectory = newTmpDir;
return true;
}
}
@Override @Override
public InputStream getUploadInput(final UploadFile upload) throws IOException{ public InputStream getUploadInput(final UploadFile upload) throws IOException{
// Check the source file: // Check the source file:
......
This diff is collapsed.
...@@ -16,7 +16,8 @@ package uws.service.request; ...@@ -16,7 +16,8 @@ package uws.service.request;
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>. * along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright 2014 - Astronomisches Rechen Institut (ARI) * Copyright 2014-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/ */
import java.io.File; import java.io.File;
...@@ -28,36 +29,40 @@ import java.util.Map; ...@@ -28,36 +29,40 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.FileRenamePolicy;
import uws.UWSException; import uws.UWSException;
import uws.service.UWS; import uws.service.UWS;
import uws.service.file.UWSFileManager; import uws.service.file.UWSFileManager;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.FileRenamePolicy;
/** /**
* <p>Extract parameters encoded using the Content-type multipart/form-data * Extract parameters encoded using the Content-type multipart/form-data
* in an {@link HttpServletRequest}.</p> * in an {@link HttpServletRequest}.
* *
* <p> * <p>
* The created file(s) is(are) stored in the temporary upload directory ({@link UWSFileManager#TMP_UPLOAD_DIR} ; this attribute can be modified if needed). * The created file(s) is(are) stored in the temporary upload directory
* This directory is supposed to be emptied regularly in case it is forgotten at any moment by the UWS service implementation to delete unused request files. * ({@link UWSFileManager#getTmpDirectory()}. This directory is supposed to be
* emptied regularly in case it is forgotten at any moment by the service
* implementation to delete unused request files.
* </p> * </p>
* *
* <p> * <p>
* The size of the full request body is limited by the static attribute {@link #SIZE_LIMIT} before the creation of the file. * The size of the full request body is limited by the static attribute
* Its default value is: {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. * {@link #SIZE_LIMIT} before the creation of the file. Its default value is:
* {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes.
* </p> * </p>
* *
* <p> * <p>
* By default, this {@link RequestParser} overwrite parameter occurrences in the map: that's to say if a parameter is provided several times, * By default, this {@link RequestParser} overwrite parameter occurrences in
* only the last value will be kept. This behavior can be changed by overwriting the function {@link #consumeParameter(String, Object, Map)} * the map: that's to say if a parameter is provided several times, only the
* of this class. * last value will be kept. This behaviour can be changed by overwriting the
* function {@link #consumeParameter(String, Object, Map)} of this class.
* </p> * </p>
* *
* @author Gr&eacute;gory Mantelet (ARI) * @author Gr&eacute;gory Mantelet (ARI;CDS)
* @version 4.1 (12/2014) * @version 4.4 (08/2018)
* @since 4.1 * @since 4.4
*/ */
public class MultipartParser implements RequestParser { public class MultipartParser implements RequestParser {
...@@ -135,7 +140,7 @@ public class MultipartParser implements RequestParser { ...@@ -135,7 +140,7 @@ public class MultipartParser implements RequestParser {
try{ try{
// Parse the request body: // Parse the request body:
multipart = new MultipartRequest(request, UWSFileManager.TMP_UPLOAD_DIR.getPath(), (SIZE_LIMIT < 0 ? DEFAULT_SIZE_LIMIT : SIZE_LIMIT), new FileRenamePolicy(){ multipart = new MultipartRequest(request, fileManager.getTmpDirectory().getPath(), (SIZE_LIMIT < 0 ? DEFAULT_SIZE_LIMIT : SIZE_LIMIT), new FileRenamePolicy() {
@Override @Override
public File rename(File file){ public File rename(File file){
Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID);
...@@ -188,7 +193,7 @@ public class MultipartParser implements RequestParser { ...@@ -188,7 +193,7 @@ public class MultipartParser implements RequestParser {
throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, ioe, "Internal Error => Impossible to extract parameters from the Multipart HTTP request!"); throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, ioe, "Internal Error => Impossible to extract parameters from the Multipart HTTP request!");
}catch(IllegalArgumentException iae){ }catch(IllegalArgumentException iae){
String confError = iae.getMessage(); String confError = iae.getMessage();
if (UWSFileManager.TMP_UPLOAD_DIR == null) if (fileManager.getTmpDirectory() == null)
confError = "Missing upload directory!"; confError = "Missing upload directory!";
throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, iae, "Internal Error: Incorrect UPLOAD configuration: " + confError); throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, iae, "Internal Error: Incorrect UPLOAD configuration: " + confError);
} }
...@@ -217,7 +222,8 @@ public class MultipartParser implements RequestParser { ...@@ -217,7 +222,8 @@ public class MultipartParser implements RequestParser {
if (allParams.containsKey(name) && allParams.get(name) instanceof UploadFile){ if (allParams.containsKey(name) && allParams.get(name) instanceof UploadFile){
try{ try{
((UploadFile)allParams.get(name)).deleteFile(); ((UploadFile)allParams.get(name)).deleteFile();
}catch(IOException ioe){} }catch(IOException ioe){
}
} }
// Put the given value in the given map: // Put the given value in the given map:
...@@ -225,16 +231,18 @@ public class MultipartParser implements RequestParser { ...@@ -225,16 +231,18 @@ public class MultipartParser implements RequestParser {
} }
/** /**
* <p>Utility method that determines whether the content of the given request is a multipart/form-data.</p> * Utility method that determines whether the content of the given request
* is a multipart/form-data.
* *
* <p><i>Important: * <p><i>Important:
* This function just test the content-type of the request. The HTTP method (e.g. GET, POST, ...) is not tested. * This function just test the content-type of the request. The HTTP method
* (e.g. GET, POST, ...) is not tested.
* </i></p> * </i></p>
* *
* @param request The servlet request to be evaluated. Must be non-null. * @param request The servlet request to be evaluated. Must be non-null.
* *
* @return <i>true</i> if the request is multipart, * @return <code>true</code> if the request is multipart,
* <i>false</i> otherwise. * <code>false</code> otherwise.
*/ */
public static final boolean isMultipartContent(final HttpServletRequest request){ public static final boolean isMultipartContent(final HttpServletRequest request){
// Extract the content type and determine if it is a multipart request (its content type should start by multipart/form-data"): // Extract the content type and determine if it is a multipart request (its content type should start by multipart/form-data"):
......
...@@ -37,21 +37,24 @@ import uws.service.UWS; ...@@ -37,21 +37,24 @@ import uws.service.UWS;
import uws.service.file.UWSFileManager; import uws.service.file.UWSFileManager;
/** /**
* <p>This parser merely copies the whole HTTP request content inside a file. * This parser merely copies the whole HTTP request content inside a file.
* It names this file: "JDL" (Job Description Language).</p> * It names this file: "JDL" (Job Description Language).
* *
* <p> * <p>
* The created file is stored in the temporary upload directory ({@link UWSFileManager#TMP_UPLOAD_DIR} ; this attribute can be modified if needed). * The created file is stored in the temporary upload directory
* This directory is supposed to be emptied regularly in case it is forgotten at any moment by the UWS service implementation to delete unused request files. * ({@link UWSFileManager#getTmpDirectory()}. This directory is supposed to be
* emptied regularly in case it is forgotten at any moment by the service
* implementation to delete unused request files.
* </p> * </p>
* *
* <p> * <p>
* The size of the JDL is limited by the static attribute {@link #SIZE_LIMIT} before the creation of the file. * The size of the JDL is limited by the static attribute {@link #SIZE_LIMIT}
* Its default value is: {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. * before the creation of the file. Its default value is:
* {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes.
* </p> * </p>
* *
* @author Gr&eacute;gory Mantelet (ARI) * @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 4.1 (11/2014) * @version 4.4 (08/2018)
* @since 4.1 * @since 4.1
*/ */
public class NoEncodingParser implements RequestParser { public class NoEncodingParser implements RequestParser {
...@@ -106,7 +109,7 @@ public class NoEncodingParser implements RequestParser { ...@@ -106,7 +109,7 @@ public class NoEncodingParser implements RequestParser {
Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID);
if (reqID == null || !(reqID instanceof String)) if (reqID == null || !(reqID instanceof String))
reqID = (new Date()).getTime(); reqID = (new Date()).getTime();
File f = new File(UWSFileManager.TMP_UPLOAD_DIR, "REQUESTBODY_" + reqID); File f = new File(fileManager.getTmpDirectory(), "REQUESTBODY_" + reqID);
OutputStream output = null; OutputStream output = null;
InputStream input = null; InputStream input = null;
long totalLength = 0; long totalLength = 0;
...@@ -141,12 +144,14 @@ public class NoEncodingParser implements RequestParser { ...@@ -141,12 +144,14 @@ public class NoEncodingParser implements RequestParser {
if (input != null){ if (input != null){
try{ try{
input.close(); input.close();
}catch(IOException ioe2){} }catch(IOException ioe2){
}
} }
if (output != null){ if (output != null){
try{ try{
output.close(); output.close();
}catch(IOException ioe2){} }catch(IOException ioe2){
}
} }
} }
......
...@@ -169,7 +169,7 @@ public class XMLRequestParser implements RequestParser { ...@@ -169,7 +169,7 @@ public class XMLRequestParser implements RequestParser {
Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID);
if (reqID == null || !(reqID instanceof String)) if (reqID == null || !(reqID instanceof String))
reqID = (new Date()).getTime(); reqID = (new Date()).getTime();
File xmlFile = new File(UWSFileManager.TMP_UPLOAD_DIR, "JOB_DESCRIPTION_" + reqID); File xmlFile = new File(fileManager.getTmpDirectory(), "JOB_DESCRIPTION_" + reqID);
OutputStream output = null; OutputStream output = null;
InputStream input = null; InputStream input = null;
...@@ -254,12 +254,14 @@ public class XMLRequestParser implements RequestParser { ...@@ -254,12 +254,14 @@ public class XMLRequestParser implements RequestParser {
if (output != null){ if (output != null){
try{ try{
output.close(); output.close();
}catch(IOException ioe2){} }catch(IOException ioe2){
}
} }
if (input != null){ if (input != null){
try{ try{
input.close(); input.close();
}catch(IOException ioe2){} }catch(IOException ioe2){
}
} }
} }
...@@ -312,7 +314,8 @@ public class XMLRequestParser implements RequestParser { ...@@ -312,7 +314,8 @@ public class XMLRequestParser implements RequestParser {
if (input != null){ if (input != null){
try{ try{
input.close(); input.close();
}catch(IOException ioe){} }catch(IOException ioe){
}
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment