com.sap.cloud.security.ams.dcl.archivetools.ArchiveTools Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of archive-tools Show documentation
Show all versions of archive-tools Show documentation
Tools for handling AMS bundles.
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");
}
}
}