org.bonitasoft.console.common.server.servlet.FileUploadServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.bonitasoft.console.common.server.servlet.FileUploadServlet.java

Source

/**
 * Copyright (C) 2009 BonitaSoft S.A.
 * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2.0 of the License, or
 * (at your option) any later version.
 * This program 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 General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.bonitasoft.console.common.server.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.bonitasoft.forms.server.exception.FileTooBigException;
import org.codehaus.jettison.json.JSONObject;

/**
 * Servlet allowing to upload a File.
 *
 * @author Julien Mege
 */
public abstract class FileUploadServlet extends HttpServlet {

    /**
     * UID
     */
    protected static final long serialVersionUID = -948661031179067420L;

    protected static final Logger LOGGER = Logger.getLogger(FileUploadServlet.class.getName());

    protected String uploadDirectoryPath = null;

    public static final String RESPONSE_SEPARATOR = "::";

    protected static final String SUPPORTED_EXTENSIONS_PARAM = "SupportedExtensions";

    protected static final String SUPPORTED_EXTENSIONS_SEPARATOR = ",";

    protected static final String RETURN_FULL_SERVER_PATH_PARAM = "ReturnFullPath";

    protected static final String RETURN_ORIGINAL_FILENAME_PARAM = "ReturnOriginalFilename";

    protected static final String CHECK_UPLOADED_FILE_SIZE = "CheckUploadedFileSize";

    protected static final String RESPONSE_CONTENT_TYPE_PARAM = "ContentType";

    protected static final String TEXT_CONTENT_TYPE = "text";

    protected static final String JSON_CONTENT_TYPE = "json";

    protected static final String TEMP_PATH_RESPONSE_ATTRIBUTE = "tempPath";

    protected static final String FILE_NAME_RESPONSE_ATTRIBUTE = "filename";

    protected String[] supportedExtensionsList = new String[0];

    protected boolean returnFullPathInResponse = false;

    protected boolean alsoReturnOriginalFilename = false;

    protected boolean checkUploadedFileSize = false;

    protected String responseContentType = TEXT_CONTENT_TYPE;

    @Override
    public void init() throws ServletException {

        final String supportedExtensionsParam = getInitParameter(SUPPORTED_EXTENSIONS_PARAM);
        if (supportedExtensionsParam != null) {
            supportedExtensionsList = supportedExtensionsParam.split(SUPPORTED_EXTENSIONS_SEPARATOR);
        }
        alsoReturnOriginalFilename = Boolean.parseBoolean(getInitParameter(RETURN_ORIGINAL_FILENAME_PARAM));
        returnFullPathInResponse = Boolean.parseBoolean(getInitParameter(RETURN_FULL_SERVER_PATH_PARAM));
        final String responseContentTypeParam = getInitParameter(RESPONSE_CONTENT_TYPE_PARAM);
        if (responseContentTypeParam != null) {
            responseContentType = responseContentTypeParam;
        }
        checkUploadedFileSize = Boolean.parseBoolean(getInitParameter(CHECK_UPLOADED_FILE_SIZE));
    }

    protected abstract void defineUploadDirectoryPath(final HttpServletRequest request);

    protected abstract void checkUploadSize(final HttpServletRequest request, FileItem item)
            throws FileTooBigException;

    protected void setUploadDirectoryPath(final String uploadDirectoryPath) {
        this.uploadDirectoryPath = uploadDirectoryPath;
    }

    protected String getUploadDirectoryPath() {
        return uploadDirectoryPath;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void doPost(final HttpServletRequest request, final HttpServletResponse response)
            throws ServletException {
        defineUploadDirectoryPath(request);
        response.setContentType("text/plain;charset=UTF-8");
        PrintWriter responsePW = null;
        try {
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;
            }

            final File targetDirectory = new File(uploadDirectoryPath);
            if (!targetDirectory.exists()) {
                targetDirectory.mkdirs();
            }

            responsePW = response.getWriter();

            final FileItemFactory fileItemFactory = new DiskFileItemFactory();
            final ServletFileUpload serviceFileUpload = createServletFileUpload(fileItemFactory);
            final List<FileItem> items = serviceFileUpload.parseRequest(request);

            for (final FileItem item : items) {
                if (item.isFormField()) {
                    continue;
                }

                final String fileName = item.getName();

                if (checkUploadedFileSize) {
                    checkUploadSize(request, item);
                }

                // Check if extension is allowed
                if (!isSupportedExtention(fileName)) {
                    outputMediaTypeError(response, responsePW);
                    return;
                }

                // Make unique file name
                final File uploadedFile = makeUniqueFilename(targetDirectory, fileName);

                // Upload file
                item.write(uploadedFile);
                if (LOGGER.isLoggable(Level.FINEST)) {
                    LOGGER.log(Level.FINEST, "File uploaded : " + uploadedFile.getPath());
                }
                uploadedFile.deleteOnExit();

                // Response
                final String responseString;
                if (JSON_CONTENT_TYPE.equals(responseContentType)) {
                    responseString = generateResponseJson(request, fileName, uploadedFile);
                } else if (TEXT_CONTENT_TYPE.equals(responseContentType)) {
                    responseString = generateResponseString(request, fileName, uploadedFile);
                } else {
                    throw new ServletException(
                            "Unsupported content type in servlet configuration : " + responseContentType);
                }
                responsePW.print(responseString);
                responsePW.flush();
            }
        } catch (final FileTooBigException e) {
            LOGGER.log(Level.SEVERE, "File is Too Big", e);
            response.setStatus(HttpURLConnection.HTTP_ENTITY_TOO_LARGE);
            if (JSON_CONTENT_TYPE.equals(responseContentType)) {
                final Map<String, Serializable> errorResponse = new HashMap<>();
                errorResponse.put("type", "EntityTooLarge");
                errorResponse.put("message",
                        e.getFileName() + " is too large, limit is set to " + e.getMaxSize() + "Mb");
                errorResponse.put("statusCode", HttpURLConnection.HTTP_ENTITY_TOO_LARGE);
                responsePW.print(new JSONObject(errorResponse).toString());
                responsePW.flush();
            }
        } catch (final Exception e) {
            final String theErrorMessage = "Exception while uploading file.";
            if (LOGGER.isLoggable(Level.SEVERE)) {
                LOGGER.log(Level.SEVERE, theErrorMessage, e);
            }
            throw new ServletException(theErrorMessage, e);
        }
    }

    //for test purpose
    protected ServletFileUpload createServletFileUpload(final FileItemFactory fileItemFactory) {
        return new ServletFileUpload(fileItemFactory);
    }

    protected String generateResponseString(final HttpServletRequest request, final String fileName,
            final File uploadedFile) throws Exception {
        String responseString;
        if (returnFullPathInResponse) {
            responseString = uploadedFile.getPath();
        } else {
            responseString = uploadedFile.getName();
        }
        if (alsoReturnOriginalFilename) {
            responseString = responseString + RESPONSE_SEPARATOR + getFilenameLastSegment(fileName);
        }
        return responseString;
    }

    protected String generateResponseJson(final HttpServletRequest request, final String fileName,
            final File uploadedFile) throws Exception {
        final Map<String, String> responseMap = new HashMap<String, String>();
        if (alsoReturnOriginalFilename) {
            responseMap.put(FILE_NAME_RESPONSE_ATTRIBUTE, getFilenameLastSegment(fileName));
        }
        if (returnFullPathInResponse) {
            responseMap.put(TEMP_PATH_RESPONSE_ATTRIBUTE, uploadedFile.getPath());
        } else {
            responseMap.put(TEMP_PATH_RESPONSE_ATTRIBUTE, uploadedFile.getName());
        }
        return new JSONObject(responseMap).toString();
    }

    protected File makeUniqueFilename(final File targetDirectory, final String fileName) throws IOException {
        final File uploadedFile = File.createTempFile("tmp_", getExtension(fileName), targetDirectory);
        uploadedFile.deleteOnExit();
        return uploadedFile;
    }

    protected String getExtension(final String fileName) {
        String extension = "";
        final String filenameLastSegment = getFilenameLastSegment(fileName);
        final int dotPos = filenameLastSegment.lastIndexOf('.');
        if (dotPos > -1) {
            extension = filenameLastSegment.substring(dotPos);
        }
        return extension;
    }

    protected String getFilenameLastSegment(final String fileName) {
        int slashPos = fileName.lastIndexOf("/");
        if (slashPos == -1) {
            slashPos = fileName.lastIndexOf("\\");
        }
        return fileName.substring(slashPos + 1);
    }

    protected void outputMediaTypeError(final HttpServletResponse response, final PrintWriter responsePW) {
        response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
        responsePW.print("Exstention not supported.");
        responsePW.flush();
        return;
    }

    protected boolean isSupportedExtention(final String fileName) {
        if (fileName == null) {
            return false;
        }

        // if no extension specified, all extensions are allowed
        if (supportedExtensionsList.length < 1) {
            return true;
        }

        for (final String extention : supportedExtensionsList) {
            if (fileName.toLowerCase().endsWith("." + extention.toLowerCase())) {
                return true;
            }
        }

        return false;
    }
}