Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.nitorcreations.willow.deployer.download.Extractor Maven / Gradle / Ivy
package com.nitorcreations.willow.deployer.download;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_SUFFIX_EXTRACT_FILTER_GLOB;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_SUFFIX_EXTRACT_GLOB;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_SUFFIX_EXTRACT_OVERWRITE;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_SUFFIX_EXTRACT_ROOT;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_SUFFIX_EXTRACT_SKIP_GLOB;
import static com.nitorcreations.willow.deployer.PropertyKeys.PROPERTY_KEY_WORKDIR;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
@SuppressWarnings({"PMD.TooManyStaticImports", "PMD.AvoidUsingOctalValues"})
public class Extractor implements Callable {
private final Properties properties;
private final File target;
private final Logger logger;
private static final Pattern zipFilesPattern = Pattern.compile(".*?\\.zip$|.*?\\.jar$|.*?\\.war$|.*?\\.ear$", Pattern.CASE_INSENSITIVE);
private static final Pattern compressedPattern = Pattern.compile(".*?\\.gz$|.*?\\.tgz$|.*?\\.z$|.*?\\.bz2$|.*?\\.lzma$|.*?\\.arj$|.*?\\.deflate$");
private final ArchiveStreamFactory factory = new ArchiveStreamFactory();
private final CompressorStreamFactory cfactory = new CompressorStreamFactory();
private static Map perms = new HashMap();
static {
perms.put(0001, PosixFilePermission.OTHERS_EXECUTE);
perms.put(0002, PosixFilePermission.OTHERS_WRITE);
perms.put(0004, PosixFilePermission.OTHERS_READ);
perms.put(0010, PosixFilePermission.GROUP_EXECUTE);
perms.put(0020, PosixFilePermission.GROUP_WRITE);
perms.put(0040, PosixFilePermission.GROUP_READ);
perms.put(0100, PosixFilePermission.OWNER_EXECUTE);
perms.put(0200, PosixFilePermission.OWNER_WRITE);
perms.put(0400, PosixFilePermission.OWNER_READ);
}
public Extractor(Properties properties, File target) {
this.properties = properties;
this.target = target;
logger = Logger.getLogger(target.getName());
}
@Override
public Boolean call() {
if (target == null) {
return false;
}
File workDir = new File(properties.getProperty(PROPERTY_KEY_WORKDIR, "."));
boolean overwrite = "false".equalsIgnoreCase(properties.getProperty(PROPERTY_KEY_SUFFIX_EXTRACT_OVERWRITE)) ? false : true;
String extractRoot = properties.getProperty(PROPERTY_KEY_SUFFIX_EXTRACT_ROOT, workDir.getAbsolutePath());
String extractGlob = properties.getProperty(PROPERTY_KEY_SUFFIX_EXTRACT_GLOB);
String skipExtractGlob = properties.getProperty(PROPERTY_KEY_SUFFIX_EXTRACT_SKIP_GLOB);
String filterGlob = properties.getProperty(PROPERTY_KEY_SUFFIX_EXTRACT_FILTER_GLOB);
File root = new File(extractRoot);
Map replaceParameters = new HashMap<>();
for (Entry next : properties.entrySet()) {
replaceParameters.put((String) next.getKey(), (String) next.getValue());
}
try {
if (!root.isAbsolute()) {
root = new File(workDir.getCanonicalFile(), extractRoot).getCanonicalFile();
}
int entries = 0;
if (extractGlob != null || skipExtractGlob != null) {
entries = extractFile(target, replaceParameters, root, extractGlob, skipExtractGlob, filterGlob, overwrite);
}
logger.log(Level.INFO, "Processed " + entries + " entries");
return true;
} catch (IOException | CompressorException | ArchiveException e) {
logger.log(Level.WARNING, "Failed to extract " + target.getAbsolutePath(), e);
return false;
}
}
private int extractFile(File archive, Map replaceTokens, File root, String extractGlob, String skipExtractGlob, String filterGlob, boolean overwrite) throws CompressorException, IOException, ArchiveException {
Set extractMatchers = getGlobMatchers(extractGlob);
Set skipMatchers = getGlobMatchers(skipExtractGlob);
Set filterMatchers = getGlobMatchers(filterGlob);
if (zipFilesPattern.matcher(archive.getName()).matches()) {
try (ZipFile source = new ZipFile(archive)) {
return extractZip(source, root, replaceTokens, extractMatchers, skipMatchers, filterMatchers, overwrite);
}
} else {
try (InputStream in = new BufferedInputStream(new FileInputStream(archive), 8 * 1024)) {
if (compressedPattern.matcher(archive.getName()).matches()) {
try (InputStream compressed = new BufferedInputStream(cfactory.createCompressorInputStream(in), 8 * 1024)) {
try (ArchiveInputStream source = factory.createArchiveInputStream(compressed)) {
return extractArchive(source, root, replaceTokens, extractMatchers, skipMatchers, filterMatchers, overwrite);
}
}
} else {
try (ArchiveInputStream source = factory.createArchiveInputStream(in)) {
return extractArchive(source, root, replaceTokens, extractMatchers, skipMatchers, filterMatchers, overwrite);
}
}
}
}
}
private int extractArchive(ArchiveInputStream is, File destFolder, Map replaceTokens, Set extractMatchers, Set skipMatchers, Set filterMatchers, boolean overwrite) throws IOException {
ArchiveEntry entry;
int entries = 0;
while ((entry = is.getNextEntry()) != null) {
extractEntry(is, entry, destFolder, replaceTokens, extractMatchers, skipMatchers, filterMatchers, overwrite);
entries++;
}
return entries;
}
private int extractZip(ZipFile zipFile, File destFolder, Map replaceTokens, Set extractMatchers, Set skipMatchers, Set filterMatchers, boolean overwrite) throws IOException {
Enumeration en = zipFile.getEntries();
int entries = 0;
while (en.hasMoreElements()) {
ZipArchiveEntry nextEntry = en.nextElement();
extractEntry(zipFile.getInputStream(nextEntry), nextEntry, destFolder, replaceTokens, extractMatchers, skipMatchers, filterMatchers, overwrite);
entries++;
}
return entries;
}
private boolean globMatches(String path, Set matchers) {
for (PathMatcher next : matchers) {
if (next.matches(Paths.get(path))) {
return true;
}
}
return false;
}
private Set getGlobMatchers(String expressions) {
Set matchers = new LinkedHashSet<>();
if (expressions == null || expressions.isEmpty()) {
return matchers;
}
FileSystem def = FileSystems.getDefault();
for (String next : expressions.split("\\|")) {
String trimmed = next.trim();
if (!trimmed.isEmpty()) {
matchers.add(def.getPathMatcher("glob:" + trimmed));
}
}
return matchers;
}
public Set getPermissions(int mode) {
Set permissions = new HashSet();
for (Entry maskEntry : perms.entrySet()) {
int mask = maskEntry.getKey().intValue();
if (mask == (mode & mask)) {
permissions.add(maskEntry.getValue());
}
}
return permissions;
}
@SuppressWarnings("PMD.CollapsibleIfStatements")
private void extractEntry(InputStream is, ArchiveEntry entry, File destFolder, Map replaceTokens, Set extractMatchers, Set skipMatchers, Set filterMatchers, boolean overwrite) throws IOException {
File dest = new File(destFolder, entry.getName()).getCanonicalFile();
if (globMatches(entry.getName(), extractMatchers) && !globMatches(entry.getName(), skipMatchers)) {
if (entry.isDirectory()) {
FileUtil.createDir(dest);
} else {
if (dest.exists() && !overwrite) {
return;
}
FileUtil.createDir(dest.getParentFile());
if (globMatches(entry.getName(), filterMatchers)) {
FileUtil.filterStream(is, dest, replaceTokens);
} else {
FileUtil.copy(is, dest);
}
PosixFileAttributeView posix = Files.getFileAttributeView(dest.toPath(), PosixFileAttributeView.class);
Set permissions = getPermissions(getMode(entry));
if (posix != null) {
posix.setPermissions(permissions);
} else {
for (PosixFilePermission next : permissions) {
boolean userOnly = false;
if (next == PosixFilePermission.OWNER_EXECUTE || next == PosixFilePermission.OWNER_READ || next == PosixFilePermission.OWNER_WRITE) {
userOnly = true;
}
if (next == PosixFilePermission.OWNER_EXECUTE || next == PosixFilePermission.GROUP_EXECUTE || next == PosixFilePermission.OTHERS_EXECUTE) {
if (dest.setExecutable(true, userOnly)) {
logger.fine("Failed to set executable on " + dest.getAbsolutePath());
}
}
if (next == PosixFilePermission.OWNER_WRITE || next == PosixFilePermission.GROUP_WRITE || next == PosixFilePermission.OTHERS_WRITE) {
if (!dest.setWritable(true, userOnly)) {
logger.fine("Failed to set writable on " + dest.getAbsolutePath());
}
}
if (next == PosixFilePermission.OWNER_READ || next == PosixFilePermission.GROUP_READ || next == PosixFilePermission.OTHERS_READ) {
if (!dest.setReadable(true, userOnly)) {
logger.fine("Failed to set readable on " + dest.getAbsolutePath());
}
}
}
}
}
}
}
private int getMode(ArchiveEntry entry) {
Method m = null;
try {
m = entry.getClass().getMethod("getMode");
} catch (NoSuchMethodException | SecurityException e) {
logger.finer("No mode method on entry " + entry.getName());
}
if (m == null) {
if (entry instanceof ZipArchiveEntry) {
ZipArchiveEntry e = (ZipArchiveEntry) entry;
int ret = (int) ((e.getExternalAttributes() >> 16) & 0xFFF);
if (ret == 0) {
return 0644;
} else {
return ret;
}
} else {
return 0664;
}
} else {
try {
return (int) ((Number) m.invoke(entry)).longValue() & 0xFFF;
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
return 0664;
}
}
}
}