org.mycore.frontend.fileupload.MCRUploadViaFormServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.mycore.frontend.fileupload.MCRUploadViaFormServlet.java

Source

/*
 *
 * $Revision: 34120 $ $Date: 2015-12-02 23:16:17 +0100 (Mi, 02 Dez 2015) $
 *
 * This file is part of ***  M y C o R e  ***
 * See http://www.mycore.de/ for details.
 *
 * This program is free software; you can use it, redistribute it
 * and / or modify it under the terms of the GNU General Public License
 * (GPL) as published by the Free Software Foundation; either version 2
 * 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, in a file called gpl.txt or license.txt.
 * If not, write to the Free Software Foundation Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
 */

package org.mycore.frontend.fileupload;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Transaction;
import org.mycore.common.MCRSession;
import org.mycore.common.MCRSessionMgr;
import org.mycore.common.config.MCRConfiguration;
import org.mycore.common.content.streams.MCRNotClosingInputStream;
import org.mycore.frontend.MCRWebsiteWriteProtection;
import org.mycore.frontend.editor.MCREditorSubmission;
import org.mycore.frontend.editor.MCRRequestParameters;
import org.mycore.frontend.servlets.MCRServlet;
import org.mycore.frontend.servlets.MCRServletJob;

/**
 * This servlet handles form based file upload.
 *
 * @author Frank Ltzenkirchen
 * @author Thomas Scheffler (yagee)
 *
 * @version $Revision: 34120 $ $Date: 2015-12-02 23:16:17 +0100 (Mi, 02 Dez 2015) $
 *
 * @see org.mycore.frontend.fileupload.MCRUploadHandler
 */

public final class MCRUploadViaFormServlet extends MCRServlet {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LogManager.getLogger(MCRUploadViaFormServlet.class);

    @Override
    public void doGetPost(MCRServletJob job) throws Exception {
        guardWebsiteCurrentlyReadOnly();

        MCREditorSubmission sub = (MCREditorSubmission) job.getRequest().getAttribute("MCREditorSubmission");
        MCRRequestParameters rp = sub == null ? new MCRRequestParameters(job.getRequest()) : sub.getParameters();
        Optional<MCRUploadHandler> uh = getUploadHandler(rp);
        if (!uh.isPresent()) {
            job.getResponse().sendError(HttpServletResponse.SC_BAD_REQUEST, "Parameter 'uploadId' is missing!");
            return;
        }
        MCRUploadHandler handler = uh.get();
        LOGGER.info("UploadHandler form based file upload for ID " + handler.getID());

        List<FileItem> files = getUploadedFiles(rp);
        handleUploadedFiles(handler, files);

        job.getResponse().sendRedirect(job.getResponse().encodeRedirectURL(handler.getRedirectURL()));
        handler.finishUpload();
        handler.unregister();
    }

    private List<FileItem> getUploadedFiles(MCRRequestParameters rp) {
        return rp.getFileList().stream().filter(file -> file.getSize() > 0).collect(Collectors.toList());
    }

    private void guardWebsiteCurrentlyReadOnly() {
        if (MCRWebsiteWriteProtection.isActive())
            throw new RuntimeException("System is currently in read-only mode");
    }

    private Optional<MCRUploadHandler> getUploadHandler(MCRRequestParameters rp) {
        return Optional.ofNullable(rp.getParameter("uploadId")).map(MCRUploadHandlerManager::getHandler);
    }

    private void handleUploadedFiles(MCRUploadHandler handler, List<FileItem> files) throws Exception, IOException {
        int numFiles = files.size();
        LOGGER.info("UploadHandler uploading " + numFiles + " file(s)");
        handler.startUpload(numFiles);

        MCRSession session = MCRSessionMgr.getCurrentSession();
        session.commitTransaction();

        for (FileItem file : files)
            handleUploadedFile(handler, file);

        session.beginTransaction();
    }

    private void handleUploadedFile(MCRUploadHandler handler, FileItem file) throws IOException, Exception {
        InputStream in = file.getInputStream();
        String path = MCRUploadHelper.getFileName(file.getName());

        MCRConfiguration config = MCRConfiguration.instance();
        if (config.getBoolean("MCR.FileUpload.DecompressZip", true)
                && path.toLowerCase(Locale.ROOT).endsWith(".zip"))
            handleZipFile(handler, in);
        else
            handleUploadedFile(handler, file.getSize(), path, in);
    }

    private void handleUploadedFile(MCRUploadHandler handler, long size, String path, InputStream in)
            throws Exception {
        LOGGER.info("UploadServlet uploading " + path);
        MCRUploadHelper.checkPathName(path);

        Transaction tx = MCRUploadHelper.startTransaction();
        try {
            handler.receiveFile(path, in, size, null);
            MCRUploadHelper.commitTransaction(tx);
        } catch (Exception exc) {
            MCRUploadHelper.rollbackAnRethrow(tx, exc);
        }
    }

    private void handleZipFile(MCRUploadHandler handler, InputStream in) throws IOException, Exception {
        ZipInputStream zis = new ZipInputStream(in);
        MCRNotClosingInputStream nis = new MCRNotClosingInputStream(zis);
        for (ZipEntry entry; (entry = zis.getNextEntry()) != null;) {
            String path = convertAbsolutePathToRelativePath(entry.getName());
            if (entry.isDirectory())
                LOGGER.debug("UploadServlet skipping ZIP entry " + path + ", is a directory");
            else {
                handler.incrementNumFiles();
                handleUploadedFile(handler, entry.getSize(), path, nis);
            }
        }
        handler.decrementNumFiles(); //ZIP file does not count
        nis.reallyClose();
    }

    private String convertAbsolutePathToRelativePath(String path) {
        int pos = path.indexOf(":");
        if (pos >= 0) {
            path = path.substring(pos + 1);
        }
        while (path.startsWith("\\") || path.startsWith("/")) {
            path = path.substring(1);
        }
        return path;
    }
}