diff --git a/src/uws/service/file/LocalUWSFileManager.java b/src/uws/service/file/LocalUWSFileManager.java index 35cb9d1ece67beb4e71d56ddd73784e6bfe54dff..05848c10889dcf75ddd52b92f57fcda6df3740a8 100644 --- a/src/uws/service/file/LocalUWSFileManager.java +++ b/src/uws/service/file/LocalUWSFileManager.java @@ -16,7 +16,7 @@ package uws.service.file; * 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), + * Copyright 2012-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -53,26 +53,31 @@ import uws.service.log.UWSLog.LogLevel; 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> - * The name of the log file, the result files and the backup files may be customized by overriding the following functions: - * {@link #getLogFileName(uws.service.log.UWSLog.LogLevel, String)}, {@link #getResultFileName(Result, UWSJob)}, {@link #getBackupFileName(JobOwner)} and {@link #getBackupFileName()}. + * The name of the log file, the result files and the backup files may be + * 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> - * By default, results and backups are grouped by owner/user and owners/users are grouped thanks to {@link DefaultOwnerGroupIdentifier}. - * By using the appropriate constructor, you can change these default behaviors. + * By default, results and backups are grouped by owner/user and owners/users + * are grouped thanks to {@link DefaultOwnerGroupIdentifier}. By using the + * appropriate constructor, you can change these default behaviours. * </p> * * <p> - * A log file rotation is set by default so that avoiding a too big log file after several months/years of use. - * By default the rotation is done every month on the 1st at 6am. This frequency can be changed easily thanks to the function - * {@link #setLogRotationFreq(String)}. + * A log file rotation is set by default so that avoiding a too big log file + * after several months/years of use. By default the rotation is done every + * month on the 1st at 6am. This frequency can be changed easily thanks to the + * function {@link #setLogRotationFreq(String)}. * </p> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.4 (07/2018) + * @version 4.4 (08/2018) */ 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. */ 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. */ 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). @@ -439,6 +448,21 @@ public class LocalUWSFileManager implements UWSFileManager { 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 public InputStream getUploadInput(final UploadFile upload) throws IOException{ // Check the source file: diff --git a/src/uws/service/file/UWSFileManager.java b/src/uws/service/file/UWSFileManager.java index 8dbc7f7471c29141f1be524ec4d321968769c1e5..ed6e20ba4a79ebde3689a29d3e614300ed8c7be0 100644 --- a/src/uws/service/file/UWSFileManager.java +++ b/src/uws/service/file/UWSFileManager.java @@ -2,21 +2,21 @@ package uws.service.file; /* * 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-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ @@ -37,16 +37,16 @@ import uws.service.log.UWSLog.LogLevel; import uws.service.request.UploadFile; /** - * <p>Lets accessing any file managed by a UWS service.</p> - * + * Lets accessing any file managed by a UWS service. + * * <p> * It is particularly useful if you want to organize yourself * the results, log or backup file generated and read by a UWS. * </p> - * + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (11/2014) - * + * @version 4.4 (08/2018) + * * @see LocalUWSFileManager */ public interface UWSFileManager { @@ -57,26 +57,36 @@ public interface UWSFileManager { /** * Gets an input stream on the log file of this UWS. - * - * @param level Level of the message to log (DEBUG, INFO, WARNING, ERROR or FATAL). - * @param context Context of the message to log (UWS, HTTP, JOB, THREAD, ...). - * - * @return An input on the log file or <i>null</i> if there is no log file. - * - * @throws IOException If there is an error while opening an input stream on the log file. + * + * @param level Level of the message to log (DEBUG, INFO, WARNING, + * ERROR or FATAL). + * @param context Context of the message to log (UWS, HTTP, JOB, THREAD, + * ...). + * + * @return An input on the log file or <i>null</i> if there is + * no log file. + * + * @throws IOException If there is an error while opening an input stream + * on the log file. */ public InputStream getLogInput(final LogLevel level, final String context) throws IOException; /** - * <p>Gets an output stream on the log file of this UWS.</p> - * <p><i><u>note:</u> The log file must be automatically created if needed.</i></p> - * - * @param level Level of the message to log (DEBUG, INFO, WARNING, ERROR or FATAL). - * @param context Context of the message to log (UWS, HTTP, JOB, THREAD, ...). - * - * @return An output on the log file. - * - * @throws IOException If there is an error while creating the log file or while opening an output stream on it. + * Gets an output stream on the log file of this UWS. + * + * <p><i><b>Note:</b> + * The log file must be automatically created if needed. + * </i></p> + * + * @param level Level of the message to log (DEBUG, INFO, WARNING, + * ERROR or FATAL). + * @param context Context of the message to log (UWS, HTTP, JOB, THREAD, + * ...). + * + * @return An output on the log file. + * + * @throws IOException If there is an error while creating the log file or + * while opening an output stream on it. */ public PrintWriter getLogOutput(final LogLevel level, final String context) throws IOException; @@ -84,87 +94,154 @@ public interface UWSFileManager { /* UPLOADED FILES MANAGEMENT */ /* ************************* */ - /** <p>Temporary directory in which uploaded files will be stored when parsing the HTTP request.</p> - * <p><i>IMPORTANT 1: - * Uploaded files should be then moved using {@link UploadFile#move(UWSJob)} when the job creation or update is validated. + /** Temporary directory in which uploaded files will be stored when parsing + * the HTTP request. + * + * <p><i><b>Important 1:</b> + * Uploaded files should be then moved using {@link UploadFile#move(UWSJob)} + * when the job creation or update is validated. * </i></p> - * <p><i>IMPORTANT 2: - * As qualified above, this directory is <b>temporary</b>. It means that it should be emptied sometimes. - * It is particularly important because when a delete or move operation fails on uploaded files, no log or error might + * + * <p><i><b>Important 2:</b> + * As qualified above, this directory is <b>temporary</b>. It means that it + * should be emptied sometimes. It is particularly important because when a + * delete or move operation fails on uploaded files, no log or error might * be published. * </i></p> - * <p><i>Note: - * The default value is the temporary directory of the system (i.e. \tmp or \var\tmp on Unix/Linux/MacOS, c:\temp on Windows). + * + * <p><i><b>Note:</b> + * The default value is the temporary directory of the system (e.g. \tmp or + * \var\tmp on Unix/Linux/MacOS, c:\temp on Windows). * </i></p> - * @since 4.1 */ + * @since 4.1 + * @deprecated Since 4.4, use {@link #getTmpDirectory()} and + * {@link #setTmpDirectory(File)} instead. */ + @Deprecated public static File TMP_UPLOAD_DIR = new File(System.getProperty("java.io.tmpdir")); /** - * Open a stream toward the specified file, submitted inline in an HTTP request. - * + * Get the temporary directory to use in this service. + * + * <p><i><b>Note:</b> + * This directory is generally used when files are uploaded in a received + * HTTP request. + * </i></p> + * + * <p><i><b>Important:</b> + * As qualified above, this directory is <b>temporary</b>. It means that it + * should be sometimes emptied. It is particularly important because when + * a delete or move operation fails on a files, no log or error might be + * published and the files would take some space for no more reason. + * </i></p> + * + * @return The temporary directory to use. + * <i>Never <code>null</code>.</i> + * + * @since 4.4 + */ + public File getTmpDirectory(); + + /** + * Set the temporary directory to use in this service. + * + * <p><i><b>Note:</b> + * This directory is generally used when files are uploaded in a received + * HTTP request. + * </i></p> + * + * <p><i><b>Important:</b> + * As qualified above, this directory is <b>temporary</b>. It means that it + * should be sometimes emptied. It is particularly important because when + * a delete or move operation fails on a files, no log or error might be + * published and the files would take some space for no more reason. + * </i></p> + * + * @param newTmpDir The new temporary directory to use. + * + * @return <code>true</code> if the path of the temporary directory has + * been successfully updated, + * <code>false</code> otherwise (e.g. <code>null</code>, not a + * directory, not writable, not readable). + * + * @since 4.4 + */ + public boolean setTmpDirectory(final File newTmpDir); + + /** + * Open a stream toward the specified file, submitted inline in an HTTP + * request. + * * @param upload Description of the uploaded file. - * + * * @return Input to the specified uploaded file. - * + * * @throws IOException If any error occurs while opening the stream. - * + * * @since 4.1 */ public InputStream getUploadInput(final UploadFile upload) throws IOException; /** - * <p>Open a stream toward the given URI.</p> - * + * Open a stream toward the given URI. + * * <p> - * Most of the time, the given URI uses the protocol http, https or ftp, which makes - * the URI perfectly understandable by {@link URL} which is then able to open easily - * a stream (cf {@link URL#openStream()}). However, a different scheme/protocol could - * be used ; particularly VO ones like "ivo" and "vos". It is for these particular - * cases that this function has been designed: in order to provide an implementation + * Most of the time, the given URI uses the protocol http, https or ftp, + * which makes the URI perfectly understandable by {@link URL} which is + * then able to open easily a stream (cf {@link URL#openStream()}). + * However, a different scheme/protocol could be used ; particularly VO + * ones like "ivo" and "vos". It is for these particular cases that this + * function has been designed: in order to provide an implementation * supporting additional protocols. * </p> - * + * * @param uri URI of any resource to read. - * + * * @return Input to the specified resource. - * - * @throws UnsupporteURIProtocol If the protocol is not supported by this implementation. - * @throws IOException If another error occurs while opening the stream. - * + * + * @throws UnsupporteURIProtocol If the protocol is not supported by this + * implementation. + * @throws IOException If another error occurs while opening + * the stream. + * * @since 4.1 */ public InputStream openURI(final URI uri) throws UnsupportedURIProtocolException, IOException; /** - * Delete definitely the specified file, submitted inline in an HTTP request. - * + * Delete definitely the specified file, submitted inline in an HTTP + * request. + * * @param upload Description of the uploaded file. - * + * * @throws IOException If any error occurs while deleting the file. - * + * * @since 4.1 */ public void deleteUpload(final UploadFile upload) throws IOException; /** - * <p>Move the specified file from its current location to a location related to the given job.</p> - * - * <p><i>Note: - * This function is generally used only once: after the HTTP request parsing, when creating or updating a job and only if the action has been accepted. + * Move the specified file from its current location to a location related + * to the given job. + * + * <p><i><b>Note:</b> + * This function is generally used only once: after the HTTP request + * parsing, when creating or updating a job and only if the action has + * been accepted. + * </i></p> + * + * <p><i><b>Important:</b> + * This function might not be able to update the location inside the given + * {@link UploadFile}. For this reason, it is strongly recommended to not + * call directly this function, but to use {@link UploadFile#move(UWSJob)}. * </i></p> - * - * <p><b>IMPORTANT: - * This function might not be able to update the location inside the given {@link UploadFile}. For this reason, - * it is strongly recommended to not call directly this function, but to use {@link UploadFile#move(UWSJob)}. - * </b></p> - * + * * @param upload Description of the uploaded file to move. * @param destination Job in which the uploaded file will be used. - * + * * @return The new location of the uploaded file. - * + * * @throws IOException If any error occurs while moving the file. - * + * * @since 4.1 */ public String moveUpload(final UploadFile upload, final UWSJob destination) throws IOException; @@ -174,39 +251,65 @@ public interface UWSFileManager { /* *********************** */ /** - * Gets an input stream on the result file corresponding to the given job result. - * @param result The description of the result file to read. - * @param job The job of the given result. - * @return An input of the corresponding result file or <i>null</i> if there is no result file. - * @throws IOException If there is an error while opening an input stream on the result file. + * Gets an input stream on the result file corresponding to the given job + * result. + * + * @param result The description of the result file to read. + * @param job The job of the given result. + * + * @return An input of the corresponding result file + * or <i>null</i> if there is no result file. + * + * @throws IOException If there is an error while opening an input stream + * on the result file. */ public InputStream getResultInput(final Result result, final UWSJob job) throws IOException; /** - * <p>Gets an output stream on the result file corresponding to the given job result.</p> - * <p><i><u>note:</u> The result file must be automatically created if needed.</i></p> + * Gets an output stream on the result file corresponding to the given job + * result. + * + * <p><i><b>Note:</b> + * The result file must be automatically created if needed. + * </i></p> + * * @param result The description of the result file to write. * @param job The job of the given result. + * * @return An output of the corresponding result file. - * @throws IOException If there is an error while creating the result file or while opening an output stream on it. + * + * @throws IOException If there is an error while creating the result file + * or while opening an output stream on it. */ public OutputStream getResultOutput(final Result result, final UWSJob job) throws IOException; /** * Gets the size of the specified result file. - * @param result Description of the result file whose the size is wanted. - * @param job The job of the given result. - * @return The size (in bytes) of the specified result file or <i>-1</i> if unknown or the file does not exist. - * @throws IOException If there is an error while getting the result file size. + * + * @param result Description of the result file whose the size is wanted. + * @param job The job of the given result. + * + * @return The size (in bytes) of the specified result file + * or <i>-1</i> if unknown or the file does not exist. + * + * @throws IOException If there is an error while getting the result file + * size. */ public long getResultSize(final Result result, final UWSJob job) throws IOException; /** - * Deletes the result file corresponding to the given job result's description. - * @param result The description of the result file to delete. - * @param job The job of the given result. - * @return <i>true</i> if the result file has been deleted or if the result file does not exists, <i>false</i> otherwise. - * @throws IOException If there is a grave and unexpected error while deleting the result file. + * Deletes the result file corresponding to the given job result's + * description. + * + * @param result The description of the result file to delete. + * @param job The job of the given result. + * + * @return <i>true</i> if the result file has been deleted + * or if the result file does not exists, + * <i>false</i> otherwise. + * + * @throws IOException If there is a grave and unexpected error while + * deleting the result file. */ public boolean deleteResult(final Result result, final UWSJob job) throws IOException; @@ -215,39 +318,64 @@ public interface UWSFileManager { /* ********************** */ /** - * Gets an input stream on the error file corresponding to the given error and job. - * @param error The description of the error file to read. - * @param job The job of the given error. - * @return An input of the corresponding error file or <i>null</i> if there is no error file. - * @throws IOException If there is an error while opening an input stream on the error file. + * Gets an input stream on the error file corresponding to the given error + * and job. + * + * @param error The description of the error file to read. + * @param job The job of the given error. + * + * @return An input of the corresponding error file + * or <i>null</i> if there is no error file. + * + * @throws IOException If there is an error while opening an input stream + * on the error file. */ public InputStream getErrorInput(final ErrorSummary error, final UWSJob job) throws IOException; /** - * <p>Gets an output stream on the error file corresponding to the given error and job.</p> - * <p><i><u>note:</u> The error file must be automatically created if needed.</i></p> - * @param error The description of the error file to write. - * @param job The job of the given error. - * @return An output of the corresponding error file. - * @throws IOException If there is an error while creating the error file or while opening an output stream on it. + * Gets an output stream on the error file corresponding to the given error + * and job. + * + * <p><i><b>Note:</b> + * The error file must be automatically created if needed. + * </i></p> + * + * @param error The description of the error file to write. + * @param job The job of the given error. + * + * @return An output of the corresponding error file. + * + * @throws IOException If there is an error while creating the error file + * or while opening an output stream on it. */ public OutputStream getErrorOutput(final ErrorSummary error, final UWSJob job) throws IOException; /** * Gets the size of the specified error summary file. - * @param error Description of the error file whose the size is wanted. - * @param job The job of the given error. - * @return The size (in bytes) of the specified error file or <i>-1</i> if unknown or the file does not exist. - * @throws IOException If there is an error while getting the error file size. + * + * @param error Description of the error file whose the size is wanted. + * @param job The job of the given error. + * + * @return The size (in bytes) of the specified error file + * or <i>-1</i> if unknown or the file does not exist. + * + * @throws IOException If there is an error while getting the error file + * size. */ public long getErrorSize(final ErrorSummary error, final UWSJob job) throws IOException; /** - * Deletes the errir file corresponding to the given job error summary. - * @param error The description of the error file to delete. - * @param job The job of the given error. - * @return <i>true</i> if the error file has been deleted or if the error file does not exists, <i>false</i> otherwise. - * @throws IOException If there is a grave and unexpected error while deleting the error file. + * Deletes the error file corresponding to the given job error summary. + * + * @param error The description of the error file to delete. + * @param job The job of the given error. + * + * @return <i>true</i> if the error file has been deleted + * or if the error file does not exists, + * <i>false</i> otherwise. + * + * @throws IOException If there is a grave and unexpected error while + * deleting the error file. */ public boolean deleteError(final ErrorSummary error, final UWSJob job) throws IOException; @@ -256,42 +384,71 @@ public interface UWSFileManager { /* *********************** */ /** - * Gets an input stream on the backup file of ONLY the given job owner (~ UWS user). - * @param owner Owner whose the jobs must be fetched from the file on which the input stream is asked. - * @return An input on the backup file of the given owner or <i>null</i> if there is no backup file. + * Gets an input stream on the backup file of ONLY the given job owner + * (~ UWS user). + * + * @param owner Owner whose the jobs must be fetched from the file on which + * the input stream is asked. + * + * @return An input on the backup file of the given owner + * or <i>null</i> if there is no backup file. + * * @throws IllegalArgumentException If the given owner is <i>null</i>. - * @throws IOException If there is an error while opening an input stream on the backup file. + * @throws IOException If there is an error while opening an + * input stream on the backup file. */ public InputStream getBackupInput(final JobOwner owner) throws IllegalArgumentException, IOException; /** - * Gets an input stream on the backup file of ALL the job owners (~ UWS user). + * Gets an input stream on the backup file of ALL the job owners + * (~ UWS user). + * * @return An iterator on all job owner's backup file. */ public Iterator<InputStream> getAllUserBackupInputs(); /** - * <p>Gets an output stream on the backup file of ONLY the given job owner (~ UWS user).</p> - * <p><i><u>note:</u> The backup file must be automatically created if needed.</i></p> - * @param owner Owner whose the jobs must be saved in the file on which the output stream is asked. - * @return An output on the backup file of the given owner. + * Gets an output stream on the backup file of ONLY the given job owner + * (~ UWS user). + * + * <p><i><b>Note:</b> + * The backup file must be automatically created if needed. + * </i></p> + * + * @param owner Owner whose the jobs must be saved in the file on which the + * output stream is asked. + * + * @return An output on the backup file of the given owner. + * * @throws IllegalArgumentException If the given owner is <i>null</i>. - * @throws IOException If there is an error while creating the backup file or while opening an output stream on it. + * @throws IOException If there is an error while creating the + * backup file or while opening an output + * stream on it. */ public OutputStream getBackupOutput(final JobOwner owner) throws IllegalArgumentException, IOException; /** * Gets an input stream on the backup file of the whole UWS. - * @return An input on the backup file of the whole UWS or <i>null</i> if there is no backup file. - * @throws IOException If there is an error while opening an input stream of the backup file. + * + * @return An input on the backup file of the whole UWS + * or <i>null</i> if there is no backup file. + * + * @throws IOException If there is an error while opening an input stream + * of the backup file. */ public InputStream getBackupInput() throws IOException; /** - * <p>Gets an output stream on the backup file of the whole UWS.</p> - * <p><i><u>note:</u> The backup file must be automatically created if needed.</i></p> - * @return An output on the backup file of the whole UWS. - * @throws IOException If there is an error while creating the backup file or while opening an output stream on it. + * Gets an output stream on the backup file of the whole UWS. + * + * <p><i><b>Note:</b> + * The backup file must be automatically created if needed. + * </i></p> + * + * @return An output on the backup file of the whole UWS. + * + * @throws IOException If there is an error while creating the backup file + * or while opening an output stream on it. */ public OutputStream getBackupOutput() throws IOException; diff --git a/src/uws/service/request/MultipartParser.java b/src/uws/service/request/MultipartParser.java index a6760aca3527bab2871ac0b17378e92c5880fb4e..3e71762a354e647ed13d2a78bd9d5b3870c569ac 100644 --- a/src/uws/service/request/MultipartParser.java +++ b/src/uws/service/request/MultipartParser.java @@ -2,21 +2,22 @@ package uws.service.request; /* * 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 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; @@ -28,36 +29,40 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import com.oreilly.servlet.MultipartRequest; +import com.oreilly.servlet.multipart.FileRenamePolicy; + import uws.UWSException; import uws.service.UWS; 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 - * in an {@link HttpServletRequest}.</p> - * + * Extract parameters encoded using the Content-type multipart/form-data + * in an {@link HttpServletRequest}. + * * <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). - * 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. + * The created file(s) is(are) stored in the temporary upload directory + * ({@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> - * The size of the full request body is limited by the static attribute {@link #SIZE_LIMIT} before the creation of the file. - * Its default value is: {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. + * The size of the full request body is limited by the static attribute + * {@link #SIZE_LIMIT} before the creation of the file. Its default value is: + * {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. * </p> - * + * * <p> - * By default, this {@link RequestParser} overwrite parameter occurrences in the map: that's to say if a parameter is provided several times, - * only the last value will be kept. This behavior can be changed by overwriting the function {@link #consumeParameter(String, Object, Map)} - * of this class. + * By default, this {@link RequestParser} overwrite parameter occurrences in + * the map: that's to say if a parameter is provided several times, only the + * last value will be kept. This behaviour can be changed by overwriting the + * function {@link #consumeParameter(String, Object, Map)} of this class. * </p> - * - * @author Grégory Mantelet (ARI) - * @version 4.1 (12/2014) - * @since 4.1 + * + * @author Grégory Mantelet (ARI;CDS) + * @version 4.4 (08/2018) + * @since 4.4 */ public class MultipartParser implements RequestParser { @@ -87,7 +92,7 @@ public class MultipartParser implements RequestParser { /** * <p>Build a {@link MultipartParser} forbidding uploads (i.e. inline files).</p> - * + * * <p> * With this parser, when an upload (i.e. submitted inline files) is detected, an exception is thrown by {@link #parse(HttpServletRequest)} * which cancels immediately the request. @@ -99,7 +104,7 @@ public class MultipartParser implements RequestParser { /** * Build a {@link MultipartParser} allowing uploads (i.e. inline files). - * + * * @param fileManager The file manager to use in order to store any eventual upload. <b>MUST NOT be NULL</b> */ public MultipartParser(final UWSFileManager fileManager){ @@ -108,12 +113,12 @@ public class MultipartParser implements RequestParser { /** * <p>Build a {@link MultipartParser}.</p> - * + * * <p> * If the first parameter is <i>false</i>, then when an upload (i.e. submitted inline files) is detected, an exception is thrown * by {@link #parse(HttpServletRequest)} which cancels immediately the request. * </p> - * + * * @param uploadEnabled <i>true</i> to allow uploads (i.e. inline files), <i>false</i> otherwise. * If <i>false</i>, the two other parameters are useless. * @param fileManager The file manager to use in order to store any eventual upload. <b>MUST NOT be NULL</b> @@ -128,14 +133,14 @@ public class MultipartParser implements RequestParser { @Override @SuppressWarnings("unchecked") - public final Map<String,Object> parse(final HttpServletRequest request) throws UWSException{ - LinkedHashMap<String,Object> parameters = new LinkedHashMap<String,Object>(); + public final Map<String, Object> parse(final HttpServletRequest request) throws UWSException{ + LinkedHashMap<String, Object> parameters = new LinkedHashMap<String, Object>(); MultipartRequest multipart = null; try{ // 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 public File rename(File file){ Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); @@ -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!"); }catch(IllegalArgumentException iae){ String confError = iae.getMessage(); - if (UWSFileManager.TMP_UPLOAD_DIR == null) + if (fileManager.getTmpDirectory() == null) confError = "Missing upload directory!"; throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, iae, "Internal Error: Incorrect UPLOAD configuration: " + confError); } @@ -198,26 +203,27 @@ public class MultipartParser implements RequestParser { /** * <p>Consume the specified parameter: add it inside the given map.</p> - * + * * <p> * By default, this function is just putting the given value inside the map. So, if the parameter already exists in the map, * its old value will be overwritten by the given one. * </p> - * + * * <p><i>Note: * If the old value was a file, it will be deleted from the file system before its replacement in the map. * </i></p> - * + * * @param name Name of the parameter to consume. * @param value Its value. * @param allParams The list of all parameters read until now. */ - protected void consumeParameter(final String name, final Object value, final Map<String,Object> allParams){ + protected void consumeParameter(final String name, final Object value, final Map<String, Object> allParams){ // If the old value was a file, delete it before replacing its value: if (allParams.containsKey(name) && allParams.get(name) instanceof UploadFile){ try{ ((UploadFile)allParams.get(name)).deleteFile(); - }catch(IOException ioe){} + }catch(IOException ioe){ + } } // Put the given value in the given map: @@ -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: - * 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> * * @param request The servlet request to be evaluated. Must be non-null. * - * @return <i>true</i> if the request is multipart, - * <i>false</i> otherwise. + * @return <code>true</code> if the request is multipart, + * <code>false</code> otherwise. */ 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"): diff --git a/src/uws/service/request/NoEncodingParser.java b/src/uws/service/request/NoEncodingParser.java index 6ebcbd19e0cad6c5cc02dc3f8de98e4e8a975cee..1a2b5ac98904cf4be2d6fcbfc851287bdb9cbf9d 100644 --- a/src/uws/service/request/NoEncodingParser.java +++ b/src/uws/service/request/NoEncodingParser.java @@ -2,20 +2,20 @@ package uws.service.request; /* * 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 2014 - Astronomisches Rechen Institut (ARI) */ @@ -37,21 +37,24 @@ import uws.service.UWS; import uws.service.file.UWSFileManager; /** - * <p>This parser merely copies the whole HTTP request content inside a file. - * It names this file: "JDL" (Job Description Language).</p> - * + * This parser merely copies the whole HTTP request content inside a file. + * It names this file: "JDL" (Job Description Language). + * * <p> - * The created file is stored in the temporary upload directory ({@link UWSFileManager#TMP_UPLOAD_DIR} ; this attribute can be modified if needed). - * 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. + * The created file is stored in the temporary upload directory + * ({@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> - * The size of the JDL is limited by the static attribute {@link #SIZE_LIMIT} before the creation of the file. - * Its default value is: {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. + * The size of the JDL is limited by the static attribute {@link #SIZE_LIMIT} + * before the creation of the file. Its default value is: + * {@link #DEFAULT_SIZE_LIMIT}={@value #DEFAULT_SIZE_LIMIT} bytes. * </p> - * - * @author Grégory Mantelet (ARI) - * @version 4.1 (11/2014) + * + * @author Grégory Mantelet (CDS;ARI) + * @version 4.4 (08/2018) * @since 4.1 */ public class NoEncodingParser implements RequestParser { @@ -76,7 +79,7 @@ public class NoEncodingParser implements RequestParser { /** * Build the request parser. - * + * * @param fileManager A file manager. <b>MUST NOT be NULL</b> */ public NoEncodingParser(final UWSFileManager fileManager){ @@ -86,10 +89,10 @@ public class NoEncodingParser implements RequestParser { } @Override - public Map<String,Object> parse(final HttpServletRequest request) throws UWSException{ + public Map<String, Object> parse(final HttpServletRequest request) throws UWSException{ // Check the request size: if (request.getContentLength() <= 0) - return new HashMap<String,Object>(); + return new HashMap<String, Object>(); else if (request.getContentLength() > (SIZE_LIMIT < 0 ? DEFAULT_SIZE_LIMIT : SIZE_LIMIT)) throw new UWSException("JDL too big (>" + SIZE_LIMIT + " bytes) => Request rejected! You should see with the service administrator to extend this limit."); @@ -106,7 +109,7 @@ public class NoEncodingParser implements RequestParser { Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); if (reqID == null || !(reqID instanceof String)) 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; InputStream input = null; long totalLength = 0; @@ -119,13 +122,13 @@ public class NoEncodingParser implements RequestParser { if (len <= 0){ output.close(); f.delete(); - HashMap<String,Object> params = new HashMap<String,Object>(1); + HashMap<String, Object> params = new HashMap<String, Object>(1); params.put(paramName, ""); return params; }else if (len <= 2048 && request.getMethod() != null && request.getMethod().equalsIgnoreCase("put") && request.getContentType() != null && request.getContentType().toLowerCase().startsWith("text/plain")){ output.close(); f.delete(); - HashMap<String,Object> params = new HashMap<String,Object>(1); + HashMap<String, Object> params = new HashMap<String, Object>(1); params.put(paramName, new String(buffer, 0, len)); return params; }else{ @@ -141,12 +144,14 @@ public class NoEncodingParser implements RequestParser { if (input != null){ try{ input.close(); - }catch(IOException ioe2){} + }catch(IOException ioe2){ + } } if (output != null){ try{ output.close(); - }catch(IOException ioe2){} + }catch(IOException ioe2){ + } } } @@ -156,7 +161,7 @@ public class NoEncodingParser implements RequestParser { lob.length = totalLength; // Create the parameters map: - HashMap<String,Object> parameters = new HashMap<String,Object>(); + HashMap<String, Object> parameters = new HashMap<String, Object>(); parameters.put(paramName, lob); return parameters; diff --git a/src/uws/service/request/XMLRequestParser.java b/src/uws/service/request/XMLRequestParser.java index f3cbeba0b5acf2d26d78bc05c9e4621aa15ba864..84e011100bb8045bd510da10b58b450f34f7b606 100644 --- a/src/uws/service/request/XMLRequestParser.java +++ b/src/uws/service/request/XMLRequestParser.java @@ -160,7 +160,7 @@ public class XMLRequestParser implements RequestParser { } @Override - public Map<String,Object> parse(final HttpServletRequest request) throws UWSException{ + public Map<String, Object> parse(final HttpServletRequest request) throws UWSException{ // Result of the request parsing => a JobInfo containing or pointing toward the sent request content: XMLJobInfo jobDesc = null; @@ -169,7 +169,7 @@ public class XMLRequestParser implements RequestParser { Object reqID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID); if (reqID == null || !(reqID instanceof String)) 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; InputStream input = null; @@ -254,12 +254,14 @@ public class XMLRequestParser implements RequestParser { if (output != null){ try{ output.close(); - }catch(IOException ioe2){} + }catch(IOException ioe2){ + } } if (input != null){ try{ input.close(); - }catch(IOException ioe2){} + }catch(IOException ioe2){ + } } } @@ -268,7 +270,7 @@ public class XMLRequestParser implements RequestParser { request.setAttribute(UWS.REQ_ATTRIBUTE_JOB_DESCRIPTION, jobDesc); // Return an empty map => no parameter has been directly provided: - return new HashMap<String,Object>(0); + return new HashMap<String, Object>(0); } /** @@ -312,7 +314,8 @@ public class XMLRequestParser implements RequestParser { if (input != null){ try{ input.close(); - }catch(IOException ioe){} + }catch(IOException ioe){ + } } } }