groupdocs-conversion/GroupDocs.Conversion-for-Java-Dropwizard

View on GitHub
src/main/java/com/groupdocs/ui/common/resources/Resources.java

Summary

Maintainability
A
2 hrs
Test Coverage
package com.groupdocs.ui.common.resources;

import com.google.common.collect.Lists;
import com.groupdocs.ui.common.config.GlobalConfiguration;
import com.groupdocs.ui.common.exception.TotalGroupDocsException;
import io.dropwizard.jetty.ConnectorFactory;
import io.dropwizard.jetty.HttpConnectorFactory;
import io.dropwizard.server.SimpleServerFactory;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import java.io.*;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Resources
 *
 * @author Aspose Pty Ltd
 */
public abstract class Resources {
    protected final String DEFAULT_CHARSET = "UTF-8";
    protected final GlobalConfiguration globalConfiguration;

    private static final ZoneId GMT = ZoneId.of("GMT");

    /**
     * Get path to storage. Different for different products
     *
     * @param params parameters for calculating the path
     * @return path to files storage
     */
    protected abstract String getStoragePath(Map<String, Object> params);

    /**
     * Internal upload file into server
     *
     * @param documentUrl url for document
     * @param inputStream file stream
     * @param fileDetail file description
     * @param rewrite flag for rewriting file
     * @param params parameters for creating path to files storage
     * @return path to file in storage
     */
    protected String uploadFile(String documentUrl, InputStream inputStream, FormDataContentDisposition fileDetail, boolean rewrite, Map<String, Object> params) {
        InputStream uploadedInputStream = null;
        String pathname;
        try {
            String fileName;
            if (StringUtils.isEmpty(documentUrl)) {
                // get the InputStream to store the file
                uploadedInputStream = inputStream;
                fileName = fileDetail.getFileName();
            } else {
                // get the InputStream from the URL
                URL url =  new URL(documentUrl);
                uploadedInputStream = url.openStream();
                fileName = FilenameUtils.getName(url.getPath());
            }
            // get documents storage path
            String documentStoragePath = getStoragePath(params);
            // save the file
            pathname = String.format("%s%s%s", documentStoragePath, File.separator, fileName);
            File file = new File(pathname);
            // check rewrite mode
            if (rewrite) {
                // save file with rewrite if exists
                Files.copy(uploadedInputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } else {
                if (file.exists()){
                    // get file with new name
                    file = getFreeFileName(documentStoragePath, fileName);
                }
                // save file with out rewriting
                Path path = file.toPath();
                Files.copy(uploadedInputStream, path);
                pathname = path.toString();
            }
        } catch(Exception ex) {
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        } finally {
            try {
                uploadedInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return pathname;
    }

    /**
     * Date formats with time zone as specified in the HTTP RFC.
     * @see <a href="https://tools.ietf.org/html/rfc7231#section-7.1.1.1">Section 7.1.1.1 of RFC 7231</a>
     */
    private static final DateTimeFormatter[] DATE_FORMATTERS = new DateTimeFormatter[] {
            DateTimeFormatter.RFC_1123_DATE_TIME,
            DateTimeFormatter.ofPattern("EEEE, dd-MMM-yy HH:mm:ss zz", Locale.US),
            DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy",Locale.US).withZone(GMT)
    };

    /**
     * Fill Header Content-disposition parameter for download file
     *
     * @param response http response to fill header
     * @param fileName name of file
     */
    protected void fillResponseHeaderDisposition(HttpServletResponse response, String fileName) {
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
    }

    /**
     * Download file
     *
     * @param response http response
     * @param pathToFile path to file
     */
    protected void downloadFile(HttpServletResponse response, String pathToFile) {
        String fileName = FilenameUtils.getName(pathToFile);
        // don't delete, should be before writing
        fillResponseHeaderDisposition(response, fileName);
        long length;
        try (InputStream inputStream = new FileInputStream(pathToFile);
             OutputStream outputStream = response.getOutputStream()){
            // download the document
            length = IOUtils.copyLarge(inputStream, outputStream);
        } catch (Exception ex){
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
        // set response content disposition
        addFileDownloadHeaders(response, fileName, length);
    }

    /**
     * Constructor
     * @param globalConfiguration global application configuration
     * @throws UnknownHostException
     */
    public Resources(GlobalConfiguration globalConfiguration) throws UnknownHostException {
        this.globalConfiguration = globalConfiguration;

        // set HTTP port
        SimpleServerFactory serverFactory = (SimpleServerFactory) globalConfiguration.getServerFactory();
        ConnectorFactory connector = serverFactory.getConnector();
        globalConfiguration.getServer().setHttpPort(((HttpConnectorFactory) connector).getPort());

        // set host address
        String hostAddress = globalConfiguration.getApplication().getHostAddress();
        if (StringUtils.isEmpty(hostAddress) || hostAddress.startsWith("${")) {
            globalConfiguration.getApplication().setHostAddress(InetAddress.getLocalHost().getHostAddress());
        }
    }

    /**
     * Rename file if exist
     * @param directory directory where files are located
     * @param fileName file name
     * @return new file with new file name
     */
    protected File getFreeFileName(String directory, String fileName){
        File file = null;
        try {
            File folder = new File(directory);
            File[] listOfFiles = folder.listFiles();
            for (int i = 0; i < listOfFiles.length; i++) {
                int number = i + 1;
                String newFileName = FilenameUtils.removeExtension(fileName) + "-Copy(" + number + ")." + FilenameUtils.getExtension(fileName);
                file = new File(directory + File.separator + newFileName);
                if(file.exists()) {
                    continue;
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * Fill header HTTP response with file data
     */
    public void addFileDownloadHeaders(HttpServletResponse response, String fileName, Long fileLength) {
        Map<String, List<String>> fileDownloadHeaders = createFileDownloadHeaders(fileName, fileLength, MediaType.APPLICATION_OCTET_STREAM);
        for (Map.Entry<String, List<String>> entry : fileDownloadHeaders.entrySet()) {
            for (String value : entry.getValue()) {
                response.addHeader(entry.getKey(), value);
            }
        }
    }

    /**
     * Get headers for downloading files
     */
    private static Map<String, List<String>> createFileDownloadHeaders(String fileName, Long fileLength, String mediaType) {
        Map<String, List<String>> httpHeaders = new HashMap<>();
        httpHeaders.put("Content-disposition", Lists.newArrayList("attachment; filename=" + fileName));
        httpHeaders.put("Content-Type", Lists.newArrayList(mediaType));
        httpHeaders.put("Content-Description", Lists.newArrayList("File Transfer"));
        httpHeaders.put("Content-Transfer-Encoding", Lists.newArrayList("binary"));
        httpHeaders.put("Expires", Lists.newArrayList(formatDate(0)));
        httpHeaders.put("Cache-Control", Lists.newArrayList("must-revalidate"));
        httpHeaders.put("Pragma", Lists.newArrayList("public"));
        if (fileLength != null) {
            httpHeaders.put("Content-Length", Lists.newArrayList(Long.toString(fileLength)));
        }
        return httpHeaders;
    }

    private static String formatDate(long date) {
        Instant instant = Instant.ofEpochMilli(date);
        ZonedDateTime time = ZonedDateTime.ofInstant(instant, GMT);
        return DATE_FORMATTERS[0].format(time);
    }

}