org.digidoc4j.DataFile.java Source code

Java tutorial

Introduction

Here is the source code for org.digidoc4j.DataFile.java

Source

/* DigiDoc4J library
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*/

package org.digidoc4j;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.apache.commons.io.IOUtils;
import org.digidoc4j.exceptions.DigiDoc4JException;
import org.digidoc4j.exceptions.InvalidDataFileException;
import org.digidoc4j.exceptions.TechnicalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.digidoc4j.impl.StreamDocument;
import eu.europa.esig.dss.DSSDocument;
import eu.europa.esig.dss.DSSException;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.Digest;
import eu.europa.esig.dss.DigestAlgorithm;
import eu.europa.esig.dss.FileDocument;
import eu.europa.esig.dss.InMemoryDocument;
import eu.europa.esig.dss.MimeType;

/**
 * Data file wrapper providing methods for handling signed files or files to be signed in Container.
 */
public class DataFile implements Serializable {
    private static final Logger logger = LoggerFactory.getLogger(DataFile.class);

    private DSSDocument document = null;
    private Digest digest = null;
    private String id;

    /**
     * Creates container.
     *
     * @param path     file name with path
     * @param mimeType MIME type of the data file, for example 'text/plain' or 'application/msword'
     */
    public DataFile(String path, String mimeType) {
        logger.debug("Path: " + path + ", mime type: " + mimeType);
        try {
            document = new FileDocument(path);
            document.setMimeType(getMimeType(mimeType));
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new InvalidDataFileException(e);
        }
    }

    /**
     * Creates in memory document container.
     *
     * @param data     file content
     * @param fileName file name with path
     * @param mimeType MIME type of the data file, for example 'text/plain' or 'application/msword'
     */
    public DataFile(byte[] data, String fileName, String mimeType) {
        logger.debug("File name: " + fileName + ", mime type: " + mimeType);
        ByteArrayInputStream stream = new ByteArrayInputStream(data);
        document = new InMemoryDocument(stream, fileName, getMimeType(mimeType));
        IOUtils.closeQuietly(stream);
    }

    /**
     * Creates in memory document container.
     *
     * @param stream   file content from stream
     * @param fileName file name with path
     * @param mimeType MIME type of the stream file, for example 'text/plain' or 'application/msword'
     */
    public DataFile(InputStream stream, String fileName, String mimeType) {
        logger.debug("File name: " + fileName + ", mime type: " + mimeType);
        try {
            document = new InMemoryDocument(stream, fileName, getMimeType(mimeType));
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new InvalidDataFileException(e);
        }
    }

    protected DataFile(DSSDocument document) {
        this.document = document;
    }

    protected DataFile() {
    }

    protected MimeType getMimeType(String mimeType) {
        try {
            MimeType mimeTypeCode = MimeType.fromMimeTypeString(mimeType);
            logger.debug("Mime type: ", mimeTypeCode);
            return mimeTypeCode;
        } catch (DSSException e) {
            logger.error(e.getMessage());
            throw new InvalidDataFileException(e);
        }
    }

    /**
     * Calculates digest http://www.w3.org/2001/04/xmlenc#sha256 for the data file.
     * If the digest has already been calculated it will return it, otherwise it calculates the digest.
     * <p/>
     *
     * @return calculated digest
     * @throws Exception thrown if the file does not exist or the digest calculation fails.
     */
    public byte[] calculateDigest() throws Exception {
        logger.debug("");
        return calculateDigest(new URL("http://www.w3.org/2001/04/xmlenc#sha256"));
    }

    /**
     * Calculates digest for data file. If digest is already calculated returns it, otherwise calculates the digest.
     * <p>Supported uris for BDoc:</p>
     * <br>http://www.w3.org/2000/09/xmldsig#sha1
     * <br>http://www.w3.org/2001/04/xmldsig-more#sha224
     * <br>http://www.w3.org/2001/04/xmlenc#sha256
     * <br>http://www.w3.org/2001/04/xmldsig-more#sha384
     * <br>http://www.w3.org/2001/04/xmlenc#sha512
     * <p>In case of DDoc files the parameter is ignored and SHA1 hash is always returned</p>
     *
     * @param method method uri for calculating the digest
     * @return calculated digest
     */
    public byte[] calculateDigest(URL method) { // TODO exceptions to throw
        logger.debug("URL method: " + method);
        if (digest == null) {
            DigestAlgorithm digestAlgorithm = DigestAlgorithm.forXML(method.toString());
            digest = new Digest(digestAlgorithm, calculateDigestInternal(digestAlgorithm));
        } else {
            logger.debug("Returning existing digest value");
        }
        return digest.getValue();
    }

    /**
     * @param digestType digest algorithm type
     * @return digest algorithm uri
     */
    public byte[] calculateDigest(org.digidoc4j.DigestAlgorithm digestType) {
        logger.debug("");
        return calculateDigest(digestType.uri());
    }

    byte[] calculateDigestInternal(DigestAlgorithm digestAlgorithm) {
        logger.debug("Digest algorithm: " + digestAlgorithm);
        return DSSUtils.digest(digestAlgorithm, getBytes());
    }

    /**
     * Returns the data file name.
     *
     * @return filename
     */
    public String getName() {
        String documentName = document.getName();
        String name = new File(documentName).getName();
        logger.trace("File name: for document " + documentName + " is " + name);
        return name;
    }

    /**
     * Returns file ID
     * For BDoc it will return the filename
     *
     * @return id or name
     */
    public String getId() {
        logger.debug("");
        return (id == null ? getName() : id);
    }

    /**
     * Returns the data file size.
     *
     * @return file size in bytes
     */
    public long getFileSize() {
        logger.debug("");
        long fileSize;
        if (document instanceof StreamDocument || document instanceof FileDocument) {
            try {
                fileSize = Files.size(Paths.get(document.getAbsolutePath()));
                logger.debug("Document size: " + fileSize);
                return fileSize;
            } catch (IOException e) {
                logger.error(e.getMessage());
                throw new DigiDoc4JException(e);
            }
        }
        fileSize = getBytes().length;
        logger.debug("File document size: " + fileSize);
        return fileSize;
    }

    /**
     * Returns the file media type.
     *
     * @return media type
     */
    public String getMediaType() {
        logger.debug("");
        String mediaType = document.getMimeType().getMimeTypeString();
        logger.debug("Media type is: " + mediaType);
        return mediaType;
    }

    public void setMediaType(String mediaType) {
        MimeType mimeType = getMimeType(mediaType);
        document.setMimeType(mimeType);
    }

    /**
     * Saves a copy of the data file as a file to the specified stream.
     *
     * @param out stream where data is written to
     * @throws java.io.IOException on file write error
     */
    public void saveAs(OutputStream out) throws IOException {
        logger.debug("");
        out.write(getBytes());
    }

    /**
     * Saves a copy of the data file as a file with the specified file name.
     *
     * @param path full file path where the data file should be saved to. If the file exists it will be overwritten
     */
    //TODO exception - method throws DSSException which can be caused by other exceptions
    public void saveAs(String path) {
        try {
            logger.debug("Path: " + path);
            document.save(path);
        } catch (IOException e) {
            logger.error("Failed to save path " + path);
            throw new TechnicalException("Failed to save path " + path, e);
        }
    }

    /**
     * Gives file bytes
     *
     * @return data as bytes
     */
    public byte[] getBytes() {
        logger.debug("");
        try {
            return IOUtils.toByteArray(document.openStream());
        } catch (IOException e) {
            throw new TechnicalException("Error reading document bytes: " + e.getMessage(), e);
        }
    }

    /**
     * Gives data file as stream
     *
     * @return data file stream
     */
    public InputStream getStream() {
        logger.debug("");
        return document.openStream();
    }

    /**
     * Set id for the dataFile (DDoc usage only)
     *
     * @param dataFileId id for the dataFile
     */
    public void setId(String dataFileId) {
        logger.debug("");
        this.id = dataFileId;
    }

    public DSSDocument getDocument() {
        return document;
    }

    protected void setDocument(DSSDocument document) {
        this.document = document;
    }
}