/
ArchiveExtractor.java
142 lines (128 loc) · 6.15 KB
/
ArchiveExtractor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.github.eirslett.maven.plugins.frontend.lib;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.AccessDeniedException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.codehaus.plexus.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ArchiveExtractionException extends Exception {
ArchiveExtractionException(String message) {
super(message);
}
ArchiveExtractionException(String message, Throwable cause) {
super(message, cause);
}
}
interface ArchiveExtractor {
public void extract(String archive, String destinationDirectory) throws ArchiveExtractionException;
}
final class DefaultArchiveExtractor implements ArchiveExtractor {
private static final Logger LOG = LoggerFactory.getLogger(DefaultArchiveExtractor.class);
private void prepDestination(File path, boolean directory) throws IOException {
if (directory) {
path.mkdirs();
} else {
if (!path.getParentFile().exists()) {
path.getParentFile().mkdirs();
}
if(!path.getParentFile().canWrite()) {
throw new AccessDeniedException(
String.format("Could not get write permissions for '%s'", path.getParentFile().getAbsolutePath()));
}
}
}
@Override
public void extract(String archive, String destinationDirectory) throws ArchiveExtractionException {
final File archiveFile = new File(archive);
try (FileInputStream fis = new FileInputStream(archiveFile)) {
if ("msi".equals(FileUtils.getExtension(archiveFile.getAbsolutePath()))) {
String command = "msiexec /a " + archiveFile.getAbsolutePath() + " /qn TARGETDIR=\""
+ destinationDirectory + "\"";
Process child = Runtime.getRuntime().exec(command);
try {
int result = child.waitFor();
if (result != 0) {
throw new ArchiveExtractionException(
"Could not extract " + archiveFile.getAbsolutePath() + "; return code " + result);
}
} catch (InterruptedException e) {
throw new ArchiveExtractionException(
"Unexpected interruption of while waiting for extraction process", e);
}
} else if ("zip".equals(FileUtils.getExtension(archiveFile.getAbsolutePath()))) {
ZipFile zipFile = new ZipFile(archiveFile);
try {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
final File destPath = new File(destinationDirectory + File.separator + entry.getName());
prepDestination(destPath, entry.isDirectory());
if(!entry.isDirectory()){
InputStream in = null;
OutputStream out = null;
try {
in = zipFile.getInputStream(entry);
out = new FileOutputStream(destPath);
IOUtils.copy(in, out);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
}
} finally {
zipFile.close();
}
} else {
// TarArchiveInputStream can be constructed with a normal FileInputStream if
// we ever need to extract regular '.tar' files.
TarArchiveInputStream tarIn = null;
try {
tarIn = new TarArchiveInputStream(new GzipCompressorInputStream(fis));
TarArchiveEntry tarEntry = tarIn.getNextTarEntry();
String canonicalDestinationDirectory = new File(destinationDirectory).getCanonicalPath();
while (tarEntry != null) {
// Create a file for this tarEntry
final File destPath = new File(destinationDirectory + File.separator + tarEntry.getName());
prepDestination(destPath, tarEntry.isDirectory());
if (!destPath.getCanonicalPath().startsWith(canonicalDestinationDirectory)) {
throw new IOException(
"Expanding " + tarEntry.getName() + " would create file outside of " + canonicalDestinationDirectory
);
}
if (!tarEntry.isDirectory()) {
destPath.createNewFile();
boolean isExecutable = (tarEntry.getMode() & 0100) > 0;
destPath.setExecutable(isExecutable);
OutputStream out = null;
try {
out = new FileOutputStream(destPath);
IOUtils.copy(tarIn, out);
} finally {
IOUtils.closeQuietly(out);
}
}
tarEntry = tarIn.getNextTarEntry();
}
} finally {
IOUtils.closeQuietly(tarIn);
}
}
} catch (IOException e) {
throw new ArchiveExtractionException("Could not extract archive: '"
+ archive
+ "'", e);
}
}
}