diff --git a/core/pom.xml b/core/pom.xml
index 53cc2a51d8..f2ab73fd6c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -276,11 +276,6 @@ THE SOFTWARE.
commons-beanutils
1.8.3
-
- org.apache.commons
- commons-compress
- 1.9
-
javax.mail
mail
diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java
index 7a75f27d05..d2778ba37e 100644
--- a/core/src/main/java/hudson/FilePath.java
+++ b/core/src/main/java/hudson/FilePath.java
@@ -33,6 +33,7 @@ import hudson.model.AbstractProject;
import hudson.model.Computer;
import hudson.model.Item;
import hudson.model.TaskListener;
+import hudson.org.apache.tools.tar.TarInputStream;
import hudson.os.PosixAPI;
import hudson.os.PosixException;
import hudson.remoting.Callable;
@@ -69,6 +70,7 @@ import org.apache.commons.io.input.CountingInputStream;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.tar.TarEntry;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.kohsuke.stapler.Stapler;
@@ -118,8 +120,6 @@ import static hudson.Util.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jenkins.security.MasterToSlaveCallable;
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.jenkinsci.remoting.RoleChecker;
import org.jenkinsci.remoting.RoleSensitive;
@@ -2268,15 +2268,12 @@ public final class FilePath implements Serializable {
/**
* Reads from a tar stream and stores obtained files to the base dir.
- * @since TODO supports large files > 10 GB, migration to commons-compress
*/
private void readFromTar(String name, File baseDir, InputStream in) throws IOException {
- TarArchiveInputStream t = new TarArchiveInputStream(in);
-
- // TarInputStream t = new TarInputStream(in);
+ TarInputStream t = new TarInputStream(in);
try {
- TarArchiveEntry te;
- while ((te = t.getNextTarEntry()) != null) {
+ TarEntry te;
+ while ((te = t.getNextEntry()) != null) {
File f = new File(baseDir,te.getName());
if(te.isDirectory()) {
mkdirs(f);
@@ -2285,7 +2282,8 @@ public final class FilePath implements Serializable {
if (parent != null) mkdirs(parent);
writing(f);
- if (te.isSymbolicLink()) {
+ byte linkFlag = (Byte) LINKFLAG_FIELD.get(te);
+ if (linkFlag==TarEntry.LF_SYMLINK) {
new FilePath(f).symlinkTo(te.getLinkName(), TaskListener.NULL);
} else {
IOUtils.copy(t,f);
@@ -2302,6 +2300,8 @@ public final class FilePath implements Serializable {
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // process this later
throw new IOException("Failed to extract "+name,e);
+ } catch (IllegalAccessException e) {
+ throw new IOException("Failed to extract "+name,e);
} finally {
t.close();
}
@@ -2725,6 +2725,20 @@ public final class FilePath implements Serializable {
}
};
+ private static final Field LINKFLAG_FIELD = getTarEntryLinkFlagField();
+
+ private static Field getTarEntryLinkFlagField() {
+ try {
+ Field f = TarEntry.class.getDeclaredField("linkFlag");
+ f.setAccessible(true);
+ return f;
+ } catch (SecurityException e) {
+ throw new AssertionError(e);
+ } catch (NoSuchFieldException e) {
+ throw new AssertionError(e);
+ }
+ }
+
/**
* Gets the {@link FilePath} representation of the "~" directory
* (User's home directory in the Unix sense) of the given channel.
diff --git a/core/src/main/java/hudson/org/apache/tools/tar/TarInputStream.java b/core/src/main/java/hudson/org/apache/tools/tar/TarInputStream.java
index d7d8a5b54d..f2d10c1c39 100644
--- a/core/src/main/java/hudson/org/apache/tools/tar/TarInputStream.java
+++ b/core/src/main/java/hudson/org/apache/tools/tar/TarInputStream.java
@@ -37,9 +37,8 @@ import java.io.ByteArrayOutputStream;
* methods are provided to position at each successive entry in
* the archive, and the read each entry as a normal input stream
* using read().
- * @deprecated Use {@link org.apache.commons.compress.archivers.tar.TarArchiveInputStream} instead
+ *
*/
-@Deprecated
public class TarInputStream extends FilterInputStream {
// CheckStyle:VisibilityModifier OFF - bc
diff --git a/core/src/main/java/hudson/org/apache/tools/tar/TarOutputStream.java b/core/src/main/java/hudson/org/apache/tools/tar/TarOutputStream.java
index 48f4876bd4..f23e442628 100644
--- a/core/src/main/java/hudson/org/apache/tools/tar/TarOutputStream.java
+++ b/core/src/main/java/hudson/org/apache/tools/tar/TarOutputStream.java
@@ -35,11 +35,8 @@ import java.io.IOException;
* The TarOutputStream writes a UNIX tar archive as an OutputStream.
* Methods are provided to put entries, and then write their contents
* by writing to this stream using write().
- *
- * @deprecated Use {@link org.apache.commons.compress.archivers.tar.TarArchiveOutputStream} instead
*
*/
-@Deprecated
public class TarOutputStream extends FilterOutputStream {
/** Fail if a long file name is required in the archive. */
public static final int LONGFILE_ERROR = 0;
diff --git a/core/src/main/java/hudson/util/io/TarArchiver.java b/core/src/main/java/hudson/util/io/TarArchiver.java
index 4cfa5ce987..7e7a3dd4f0 100644
--- a/core/src/main/java/hudson/util/io/TarArchiver.java
+++ b/core/src/main/java/hudson/util/io/TarArchiver.java
@@ -37,8 +37,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import static org.apache.tools.tar.TarConstants.LF_SYMLINK;
@@ -49,10 +47,10 @@ import static org.apache.tools.tar.TarConstants.LF_SYMLINK;
*/
final class TarArchiver extends Archiver {
private final byte[] buf = new byte[8192];
- private final TarArchiveOutputStream tar;
+ private final TarOutputStream tar;
TarArchiver(OutputStream out) {
- tar = new TarArchiveOutputStream(new BufferedOutputStream(out) {
+ tar = new TarOutputStream(new BufferedOutputStream(out) {
// TarOutputStream uses TarBuffer internally,
// which flushes the stream for each block. this creates unnecessary
// data stream fragmentation, and flush request to a remote, which slows things down.
@@ -60,14 +58,13 @@ final class TarArchiver extends Archiver {
public void flush() throws IOException {
// so don't do anything in flush
}
- });
- tar.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
- tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+ });
+ tar.setLongFileMode(TarOutputStream.LONGFILE_GNU);
}
@Override
public void visitSymlink(File link, String target, String relativePath) throws IOException {
- TarArchiveEntry e = new TarArchiveEntry(relativePath, LF_SYMLINK);
+ TarEntry e = new TarEntry(relativePath, LF_SYMLINK);
try {
int mode = IOUtils.mode(link);
if (mode != -1) {
@@ -76,11 +73,16 @@ final class TarArchiver extends Archiver {
} catch (PosixException x) {
// ignore
}
-
- e.setLinkName(target);
- tar.putArchiveEntry(e);
- tar.closeArchiveEntry();
+ try {
+ StringBuffer linkName = (StringBuffer) LINKNAME_FIELD.get(e);
+ linkName.setLength(0);
+ linkName.append(target);
+ } catch (IllegalAccessException x) {
+ throw new IOException("Failed to set linkName", x);
+ }
+
+ tar.putNextEntry(e);
entriesWritten++;
}
@@ -95,14 +97,14 @@ final class TarArchiver extends Archiver {
if(file.isDirectory())
relativePath+='/';
- TarArchiveEntry te = new TarArchiveEntry(relativePath);
+ TarEntry te = new TarEntry(relativePath);
int mode = IOUtils.mode(file);
if (mode!=-1) te.setMode(mode);
te.setModTime(file.lastModified());
if(!file.isDirectory())
te.setSize(file.length());
- tar.putArchiveEntry(te);
+ tar.putNextEntry(te);
if (!file.isDirectory()) {
FileInputStream in = new FileInputStream(file);
@@ -115,11 +117,25 @@ final class TarArchiver extends Archiver {
}
}
- tar.closeArchiveEntry();
+ tar.closeEntry();
entriesWritten++;
}
public void close() throws IOException {
tar.close();
}
+
+ private static final Field LINKNAME_FIELD = getTarEntryLinkNameField();
+
+ private static Field getTarEntryLinkNameField() {
+ try {
+ Field f = TarEntry.class.getDeclaredField("linkName");
+ f.setAccessible(true);
+ return f;
+ } catch (SecurityException e) {
+ throw new AssertionError(e);
+ } catch (NoSuchFieldException e) {
+ throw new AssertionError(e);
+ }
+ }
}