All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.security.ams.dcl.archivetools.ArchiveTools Maven / Gradle / Ivy

The newest version!
/************************************************************************
 * © 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 ************************************************************************/
package com.sap.cloud.security.ams.dcl.archivetools;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;

public class ArchiveTools {

    private ArchiveTools() {
    }

    public static final boolean isGZipped(byte[] in) {
        if (in != null && in.length > 1) {
            return ((in[0] == (byte) (GZIPInputStream.GZIP_MAGIC))
                    && (in[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)));
        } else {
            return false;
        }
    }

    public static boolean isGZipped(InputStream is) throws IOException {
        int b0 = is.read();
        int b1 = b0 == -1 ? -1 : is.read();
        return ((byte) b0 == (byte) (GZIPInputStream.GZIP_MAGIC))
                && ((byte) b1 == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
    }

    // Move to base or tools
    private static void copy(Path from, OutputStream to, byte[] buffer) throws IOException {
        try (InputStream in = Files.newInputStream(from)) {
            int length;
            while ((length = in.read(buffer)) > 0) {
                to.write(buffer, 0, length);
            }
        }
    }

    private static final ArchiveEntryCreator TAR_ENTITY_CREATOR = new ArchiveEntryCreator() {
        @Override
        public void add(ArchiveOutputStream aos, String name, byte[] content) throws IOException {
            TarArchiveEntry tarEntry = new TarArchiveEntry(name);
            tarEntry.setSize(content.length);
            aos.putArchiveEntry(tarEntry);
            aos.write(content);
            aos.closeArchiveEntry();
        }

        @Override
        public void add(ArchiveOutputStream aos, String name, File content, byte[] buffer) throws IOException {
            TarArchiveEntry tarEntry = new TarArchiveEntry(name);
            tarEntry.setSize(content.length());
            aos.putArchiveEntry(tarEntry);
            copy(content.toPath(), aos, buffer);
            aos.closeArchiveEntry();
        }
    };

    public static final ArchiverFacade TAR_FACADE = new ArchiverFacade() {

        @Override
        public ArchiveInputStream createArchiveInputStream(InputStream is) throws IOException {
            return new TarArchiveInputStream(new GzipCompressorInputStream(is));
        }

        @Override
        public ArchiveOutputStream createArchiveOutputStream(OutputStream os) throws IOException {
            TarArchiveOutputStream taos = new TarArchiveOutputStream(
                    new GzipCompressorOutputStream(os));
            taos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
            return taos;
        }

        @Override
        public ArchiveEntryCreator getEntityCreator() {
            return TAR_ENTITY_CREATOR;
        }
    };

    private static final ArchiveEntryCreator ZIP_ENTITY_CREATOR = new ArchiveEntryCreator() {
        @Override
        public void add(ArchiveOutputStream aos, String name, byte[] content) throws IOException {
            ZipArchiveEntry tarEntry = new ZipArchiveEntry(name);
            tarEntry.setSize(content.length);
            aos.putArchiveEntry(tarEntry);
            aos.write(content);
            aos.closeArchiveEntry();
        }

        @Override
        public void add(ArchiveOutputStream aos, String name, File content, byte[] buffer) throws IOException {
            ZipArchiveEntry entry = new ZipArchiveEntry(content, name);
            aos.putArchiveEntry(entry);
            copy(content.toPath(), aos, buffer);
            aos.closeArchiveEntry();
        }
    };

    public static final ArchiverFacade ZIP_FACADE = new ArchiverFacade() {

        @Override
        public ArchiveInputStream createArchiveInputStream(InputStream is) throws IOException {
            return new ZipArchiveInputStream(is);
        }

        @Override
        public ArchiveOutputStream createArchiveOutputStream(OutputStream os) throws IOException {
            return new ZipArchiveOutputStream(os);
        }

        @Override
        public ArchiveEntryCreator getEntityCreator() {
            return ZIP_ENTITY_CREATOR;
        }
    };

    public static void compressPathToStream(ArchiverFacade facade, Path source, Predicate predicate,
            OutputStream os)
            throws IOException {
        try (ArchiveOutputStream aos = facade.createArchiveOutputStream(os)) {
            Files.walkFileTree(source, new ArchiveVisitor(source, aos, facade.getEntityCreator(), predicate));
        }
    }

    public static byte[] compressPathToBytes(ArchiverFacade ap, Path start) throws IOException {
        return compressPathToBytes(ap, start, null);
    }

    public static byte[] compressPathToBytes(ArchiverFacade ap, Path start, Predicate predicate)
            throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(8 * 1024);
        compressPathToStream(ap, start, predicate, bos);
        return bos.toByteArray();
    }

    public static void assembleOpaBundle(final File sourceDir, final File bundleFile, String manifestContent)
            throws IOException {

        assertFileNotNull(bundleFile);
        assertDirectory(sourceDir);
        assertDirectory(bundleFile.getParentFile());

        Path root = sourceDir.toPath();
        try (OutputStream fout = Files.newOutputStream(bundleFile.toPath(), StandardOpenOption.CREATE,
                StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
                ArchiveOutputStream aos = TAR_FACADE.createArchiveOutputStream(fout)) {

            ArchiveEntryCreator aec = TAR_FACADE.getEntityCreator();
            Files.walkFileTree(root, new ArchiveVisitor(root, aos, aec));

            aec.add(aos, ".manifest", manifestContent.getBytes(StandardCharsets.UTF_8));
        }
    }

    static final Pattern DCL_FILE_PATTERN = Pattern.compile(".dcl$", Pattern.CASE_INSENSITIVE);

    public static final Predicate BELONGS_IN_POLICY_BUNDLE = path -> {
        Matcher matcher = DCL_FILE_PATTERN.matcher(path.toFile().getName());
        return matcher.find();
    };

    public static void assemblePolicyBundle(final File sourceDir, final File bundleFile) throws IOException {
        assertFileNotNull(bundleFile);
        assertDirectory(sourceDir);
        assertDirectory(bundleFile.getParentFile());

        Path root = sourceDir.toPath();

        try (OutputStream fout = Files.newOutputStream(bundleFile.toPath(), StandardOpenOption.CREATE,
                StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
                ArchiveOutputStream aos = TAR_FACADE.createArchiveOutputStream(fout)) {

            ArchiveEntryCreator aec = TAR_FACADE.getEntityCreator();
            Files.walkFileTree(root, new ArchiveVisitor(root, aos, aec, BELONGS_IN_POLICY_BUNDLE));
        }
    }

    private static void assertDirectory(final File dir) throws IOException {
        if (dir == null) {
            throw new IOException("Directory must not be null");
        }

        if (!dir.exists() && !dir.mkdirs()) {
            throw new IOException("Error creating directory" + dir.getPath());
        }
    }

    private static void assertFileNotNull(File file) throws IOException {
        if (file == null) {
            throw new IOException("File must not be null");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy