eionet.gdem.utils.InputFile.java Source code

Java tutorial

Introduction

Here is the source code for eionet.gdem.utils.InputFile.java

Source

/**
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is "EINRC-7 / GDEM project".
 *
 * The Initial Developer of the Original Code is TietoEnator.
 * The Original Code code was developed for the European
 * Environment Agency (EEA) under the IDA/EINRC framework contract.
 *
 * Copyright (C) 2000-2004 by European Environment Agency.  All
 * Rights Reserved.
 *
 * Original Code: Enriko Ksper (TietoEnator)
 */

package eionet.gdem.utils;

import eionet.gdem.Properties;
import eionet.gdem.services.GDEMServices;
import eionet.gdem.services.db.dao.IHostDao;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;

/**
 * Utility class for reading files from URL.
 * The class reads the host credentials from database and if it runs in trusted mode, then it passes the basic authentication info
 * to remote server for files with limited access.
 *
 * NB! Always call close() method in finally block, otherwise the InputStream stays open.
 */
public class InputFile {

    /** */
    private static final Logger LOGGER = LoggerFactory.getLogger(InputFile.class);

    /**
     * Authentication ticket: Base64 encoded username and password.
     */
    private String ticket = null;
    /**
     * URL of the inpurt file.
     */
    private URL url = null;
    /**
     * InputStream of input file data retrieved from URLConnection.
     */
    private InputStream inputStream = null;
    /**
     * Allowed to use ticket when requesting input file.
     */
    private boolean isTrustedMode = false;
    /**
     * File name without extension extracted from URL.
     */
    private String strFileName = null;
    /**
     * File name extracted from URL.
     */
    private String strFileNameNoExtension = null;
    /**
     * Host name extracted from URL.
     */
    private String strHostName = null;
    /**
     * Folder name (path before file name) extracted from URL.
     */
    private String strFolderName = null;
    /**
     * Status of InputStream.
     */
    boolean isClosed = false;
    /**
     * Store the content of URL in local storage before streaming the result to requester.
     */
    boolean storeLocally = false;
    /**
     * Location in local storage if the file is stored locally temporarily.
     */
    String tmpFileLocation = null;

    /**
     * DAO for getting authorisation for known hosts.
     */
    private IHostDao hostDao = GDEMServices.getDaoService().getHostDao();

    /**
     * Initializes InputUrl object and sets the URI from str_url.
     *
     * @param strUrl - the URL of source file
     * @throws MalformedURLException wrong URL.
     */
    public InputFile(String strUrl) throws MalformedURLException {

        // Java's URL class doesn't escape certain characters with % +hexidecimal digits.
        // This is a bug in the class java.net.URL.
        // The correct way to create a URL object is to use class called java.net.URI (Java 1.4 and later).

        // this.url = new URL(str_url);
        setURL(strUrl);
    }

    /**
     * Get source file from url as InputStream user basic auth, if we know the credentials.
     *
     * @return InputStream of source file.
     * @throws IOException the source is not available.
     */
    public InputStream getSrcInputStream() throws IOException {
        fillInputStream();
        return inputStream;
    }

    /**
     * Save the InputFile to the specified text file with default extension.
     *
     * @return Full path of file.
     * @throws IOException if it's not possible to save file in the filesystem.
     */
    public String saveSrcFile() throws IOException {
        return saveSrcFile("xml");
    }

    /**
     * Save the InputFile to the specified text file with given extension.
     *
     * @param extension file extension to use when storing source file temporarily.
     * @return Full path of file.
     * @throws IOException if it's not possible to save file in the filesystem.
     */
    public String saveSrcFile(String extension) throws IOException {

        fillInputStream();
        String fileName = saveFileInLocalStorage(extension);

        return fileName;

    }

    /**
     * Closes InputStream of input file.
     */
    public void close() {
        try {
            if (inputStream != null && !isClosed) {
                inputStream.close();
                isClosed = true;
                if (storeLocally && tmpFileLocation != null) {
                    FileUtils.deleteQuietly(new File(tmpFileLocation));
                    LOGGER.info("Deleted temporary file: " + tmpFileLocation);
                } else {
                    LOGGER.info("Closed inputstream for URL: " + url.toString());
                }
            }
        } catch (Exception e) {
            LOGGER.warn("Closing inputstream in FileInput: " + e.toString());
        }

    }

    /**
     * Sets the authentication ticket for the source file.
     *
     * @param ticket authentication value.
     */
    public void setAuthentication(String ticket) {
        this.ticket = ticket;
    }

    /**
     * Sets the boolean to use authentication ticket for grabbing the source file or not.
     *
     * @param mode If true - use ticket
     */
    public void setTrustedMode(boolean mode) {
        this.isTrustedMode = mode;
    }

    /**
     * Extracts the file name from URL path. E.g: BasicQuality.xml where the full url is
     * http://cdrtest.eionet.europa.eu/al/eea/colrjhlyq/envrjhqwa/BasicQuality.xml
     *
     * @return file name
     */
    public String getFileName() {
        return strFileName;
    }

    /**
     * Extracts the file name without file extension from URL path. E.g: BasicQuality where the full url is
     * http://cdrtest.eionet.europa.eu/al/eea/colrjhlyq/envrjhqwa/BasicQuality.xml
     *
     * @return file name without extension
     */
    public String getFileNameNoExtension() {
        return strFileNameNoExtension;
    }

    /**
     * Return source file URL as a String.
     *
     * @return source URL as String
     */
    @Override
    public String toString() {
        return (url == null) ? null : url.toString();
    }

    /**
     * Extracts the full host name from URL. E.g: http://cdrtest.eionet.europa.eu where the full url is
     * http://cdrtest.eionet.europa.eu/al/eea/colrjhlyq/envrjhqwa/BasicQuality.xml
     *
     * @return host name from source URL.
     */
    public String getHostName() {
        return strHostName;
    }

    /**
     * Extracts the folder from URL path. E.g: /al/eea/colrjhlyq/envrjhqwa where the full url is
     * http://cdrtest.eionet.europa.eu/al/eea/colrjhlyq/envrjhqwa/BasicQuality.xml
     *
     * @return path without file name
     */
    public String getFolderName() {
        return strFolderName;
    }

    /**
     * Extracts CDR file info from URL and returns it as a map of parameters. If the source file is a file from CDR then the Map
     * contains the following parameters: envelopeurl, envelopepath, instance, filename
     *
     * @return Map of parameters extracted from URL and can be sent to Conversion Service.
     */
    public Map<String, String> getCdrParams() {
        String strEnvelopeUrl = null;
        String strInstance = null;
        Map<String, String> h = new HashMap<String, String>();
        if (getHostName() != null && getFolderName() != null) {
            strEnvelopeUrl = getHostName().concat(getFolderName());
        }
        if (getHostName() != null && getFolderName() != null && getFileName() != null) {
            strInstance = getHostName().concat(getFolderName()).concat(getFolderName().endsWith("/") ? "" : "/")
                    .concat(getFileName());
        }
        h.put("filename", getFileName());
        h.put("envelopeurl", strEnvelopeUrl);
        h.put("envelopepath", getFolderName());
        h.put("instance", strInstance);

        return h;
    }

    public URL getURL() {
        return this.url;
    }

    /**
     * Get the authentication ticket for the source file, if available.
     *
     * @return authentication ticket
     */
    public String getAuthentication() {
        if (Utils.isNullStr(ticket) && isTrustedMode) {
            String host = url.getHost();
            getHostCredentials(host);
        }
        return ticket;
    }

    /**
     * Is the URL content stored locally.
     *
     * @return true if the file is stored locally.
     */
    public boolean isStoreLocally() {
        return storeLocally;
    }

    /**
     * Set the flag to store URL content locally.
     *
     * @param storeLocally status flag to store the file locally.
     */
    public void setStoreLocally(boolean storeLocally) {
        this.storeLocally = storeLocally;
    }
    /*
         * PRIVATE METHODS
         */

    /**
     * Get Host credentials from database. There could be restriction for accessing files in different servers. Username and
     * password are saved in the T_HOST table for these cases.
     *
     * @param host URL.
     */
    private void getHostCredentials(String host) {
        try {

            Vector v = hostDao.getHosts(host);

            if (v == null) {
                return;
            }
            if (v.size() > 0) {
                Hashtable h = (Hashtable) v.get(0);
                String user = (String) h.get("user_name");
                String pwd = (String) h.get("pwd");
                this.ticket = Utils.getEncodedAuthentication(user, pwd);

            }

        } catch (Exception e) {
            LOGGER.error("Error getting host data from the DB " + e.toString());
            LOGGER.error("Conversion proceeded");
        }
    }

    /**
     * Opens URLConnection and reads the source into InputStream.
     *
     * @throws IOException in case the reading of InuptStream from URLConnection fails.
     */
    private void fillInputStream() throws IOException {

        isClosed = false;
        URLConnection uc = url.openConnection();

        ticket = getAuthentication();
        uc.addRequestProperty("Accept", "*/*");

        if (ticket != null) {
            // String auth = Utils.getEncodedAuthentication(user,pwd);
            uc.addRequestProperty("Authorization", " Basic " + ticket);
        }
        LOGGER.info("Start download file: " + url.toString());
        this.inputStream = uc.getInputStream();

        if (storeLocally) {
            tmpFileLocation = saveFileInLocalStorage("tmp");
            isClosed = false;
            inputStream = new FileInputStream(tmpFileLocation);
        }
    }

    /**
     * Stores the URL of remote file.
     *
     * @param strUrl URL of input file
     * @throws MalformedURLException Invalid URL.
     */
    private void setURL(String strUrl) throws MalformedURLException {
        try {
            URI uri = new URI(escapeSpaces(strUrl));
            parseUri(uri);

            this.url = uri.toURL();

        } catch (URISyntaxException ue) {
            throw new MalformedURLException(ue.toString());
        } catch (IllegalArgumentException ae) {
            throw new MalformedURLException(ae.toString());
        }
    }

    /**
     * Escape spaces with %20 in source URI.
     *
     * @param strUri URI of input file.
     * @return Escaped URI.
     */
    private String escapeSpaces(String strUri) {
        return Utils.Replace(strUri, " ", "%20");
    }

    /**
     * Extracts filename from URI's path [scheme:][//authority][path][?query][#fragment].
     *
     * @param uri URI of input file.
     */
    private void parseUri(URI uri) {

        this.strHostName = uri.getScheme() + "://" + uri.getAuthority();
        findFileName(uri.getPath());
    }

    /**
     * Extracts filename and folder from URI's path.
     *
     * @param strUri URI of input file.
     */
    private void findFileName(String strUri) {

        String fileName = null;
        String folderName = null;
        if (Utils.isNullStr(strUri)) {
            return;
        }

        if (strUri.endsWith("/")) {
            strUri = strUri.substring(0, strUri.length() - 1);
        }

        int lastSlash = strUri.lastIndexOf("/");

        if (lastSlash > -1) {
            fileName = strUri.substring(lastSlash + 1);
            folderName = strUri.substring(0, lastSlash);
        } else {
            fileName = strUri;
            folderName = "";
        }

        findFileNameNoExtension(fileName);

        this.strFileName = fileName;
        this.strFolderName = folderName;
    }

    /**
     * Extracts filename without file extension from URI's path.
     *
     * @param strFileName File name extracted from URI of input file.
     */
    private void findFileNameNoExtension(String strFileName) {

        String name = null;
        if (Utils.isNullStr(strFileName)) {
            return;
        }

        int lastDot = strFileName.lastIndexOf(".");

        if (lastDot > -1) {
            name = strFileName.substring(0, lastDot);
        } else {
            name = strFileName;
        }

        this.strFileNameNoExtension = name;
    }

    /**
     * Saves the inputStream as local file in tmp folder.
     *
     * @param extension file extension
     * @return full path to file
     * @throws IOException if file system operation fails.
     */
    private String saveFileInLocalStorage(String extension) throws IOException {
        String fileName = Properties.tmpFolder + File.separatorChar + "gdem_" + System.currentTimeMillis() + "-"
                + UUID.randomUUID() + "." + extension;
        File file = new File(fileName);

        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            IOUtils.copy(inputStream, outputStream);
            LOGGER.info("File stored locally url=" + url.toString() + " at " + fileName);
        } finally {
            close();
            IOUtils.closeQuietly(outputStream);
        }

        return fileName;

    }
}