org.digidoc4j.impl.bdoc.asic.AsicContainerCreator.java Source code

Java tutorial

Introduction

Here is the source code for org.digidoc4j.impl.bdoc.asic.AsicContainerCreator.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.impl.bdoc.asic;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.digidoc4j.DataFile;
import org.digidoc4j.Signature;
import org.digidoc4j.exceptions.TechnicalException;
import org.digidoc4j.impl.bdoc.manifest.AsicManifest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.europa.esig.dss.DSSDocument;
import eu.europa.esig.dss.MimeType;

public class AsicContainerCreator {

    private static final Logger logger = LoggerFactory.getLogger(AsicContainerCreator.class);
    private final static String ZIP_ENTRY_MIMETYPE = "mimetype";
    private static final Charset CHARSET = StandardCharsets.UTF_8;
    private ZipOutputStream zipOutputStream;
    private ByteArrayOutputStream outputStream;
    private String zipComment;

    public AsicContainerCreator(File containerPathToSave) {
        logger.debug("Starting to save bdoc zip container to " + containerPathToSave);
        try {
            FileOutputStream outputStream = new FileOutputStream(containerPathToSave);
            zipOutputStream = new ZipOutputStream(new BufferedOutputStream(outputStream), CHARSET);
        } catch (FileNotFoundException e) {
            logger.error("Unable to create BDoc ZIP container: " + e.getMessage());
            throw new TechnicalException("Unable to create BDoc ZIP container", e);
        }
    }

    public AsicContainerCreator() {
        outputStream = new ByteArrayOutputStream();
        zipOutputStream = new ZipOutputStream(new BufferedOutputStream(outputStream), CHARSET);
    }

    public void finalizeZipFile() {
        logger.debug("Finalizing bdoc zip file");
        try {
            zipOutputStream.close();
        } catch (IOException e) {
            logger.error("Unable to finish creating BDoc ZIP container: " + e.getMessage());
            throw new TechnicalException("Unable to finish creating BDoc ZIP container", e);
        }
    }

    public InputStream fetchInputStreamOfFinalizedContainer() {
        logger.debug("Fetching input stream of the finalized container");
        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    public void writeAsiceMimeType() {
        logger.debug("Writing asic mime type to bdoc zip file");
        String mimeTypeString = MimeType.ASICE.getMimeTypeString();
        byte[] mimeTypeBytes = mimeTypeString.getBytes();
        ZipEntry entryMimetype = getAsicMimeTypeZipEntry(mimeTypeBytes);
        writeZipEntry(entryMimetype, mimeTypeBytes);
    }

    public void writeManifest(Collection<DataFile> dataFiles) {
        logger.debug("Writing bdoc manifest");
        AsicManifest manifest = new AsicManifest();
        manifest.addFileEntry(dataFiles);
        byte[] entryBytes = manifest.getBytes();
        writeZipEntry(new ZipEntry(AsicManifest.XML_PATH), entryBytes);
    }

    public void writeDataFiles(Collection<DataFile> dataFiles) {
        logger.debug("Adding data files to the bdoc zip container");
        for (DataFile dataFile : dataFiles) {
            String name = dataFile.getName();
            logger.debug("Adding data file " + name);
            ZipEntry entryDocument = new ZipEntry(name);
            zipOutputStream.setLevel(ZipEntry.DEFLATED);
            byte[] entryBytes = dataFile.getBytes();
            writeZipEntry(entryDocument, entryBytes);
        }
    }

    public void writeSignatures(Collection<Signature> signatures, int nextSignatureFileNameIndex) {
        logger.debug("Adding signatures to the bdoc zip container");
        int index = nextSignatureFileNameIndex;
        for (Signature signature : signatures) {
            String signatureFileName = "META-INF/signatures" + index + ".xml";
            ZipEntry entryDocument = new ZipEntry(signatureFileName);
            byte[] entryBytes = signature.getAdESSignature();
            writeZipEntry(entryDocument, entryBytes);
            index++;
        }
    }

    public void writeExistingEntries(Collection<AsicEntry> asicEntries) {
        logger.debug("Writing existing zip container entries");
        for (AsicEntry asicEntry : asicEntries) {
            DSSDocument content = asicEntry.getContent();
            byte[] entryBytes = getDocumentBytes(content);
            ZipEntry zipEntry = asicEntry.getZipEntry();
            if (!StringUtils.equalsIgnoreCase(ZIP_ENTRY_MIMETYPE, zipEntry.getName())) {
                zipOutputStream.setLevel(ZipEntry.DEFLATED);
            }
            writeZipEntryWithoutComment(zipEntry, entryBytes);
        }
    }

    public void writeContainerComment(String comment) {
        logger.debug("Writing container comment: " + comment);
        zipOutputStream.setComment(comment);
    }

    public void setZipComment(String zipComment) {
        this.zipComment = zipComment;
    }

    private ZipEntry getAsicMimeTypeZipEntry(byte[] mimeTypeBytes) {
        ZipEntry entryMimetype = new ZipEntry(ZIP_ENTRY_MIMETYPE);
        entryMimetype.setMethod(ZipEntry.STORED);
        entryMimetype.setSize(mimeTypeBytes.length);
        entryMimetype.setCompressedSize(mimeTypeBytes.length);
        CRC32 crc = new CRC32();
        crc.update(mimeTypeBytes);
        entryMimetype.setCrc(crc.getValue());
        return entryMimetype;
    }

    private void writeZipEntry(ZipEntry zipEntry, byte[] entryBytes) {
        zipEntry.setComment(zipComment);
        writeZipEntryWithoutComment(zipEntry, entryBytes);
    }

    private void writeZipEntryWithoutComment(ZipEntry zipEntry, byte[] entryBytes) {
        try {
            zipOutputStream.putNextEntry(zipEntry);
            zipOutputStream.write(entryBytes);
            zipOutputStream.closeEntry();
        } catch (IOException e) {
            logger.error("Unable to write Zip entry to BDoc container: " + e.getMessage());
            throw new TechnicalException("Unable to write Zip entry to BDoc container", e);
        }
    }

    private byte[] getDocumentBytes(DSSDocument content) {
        try {
            return IOUtils.toByteArray(content.openStream());
        } catch (IOException e) {
            logger.error("Error getting document content: " + e.getMessage());
            throw new TechnicalException("Error getting document content: " + e.getMessage(), e);
        }
    }
}