提交 4e72f92b 编写于 作者: K kohsuke

Refactored FilePath to expose the archive handling code.



git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@31064 71c3de6d-444a-0410-be80-ed276b4c234a
上级 d82b8571
......@@ -39,7 +39,6 @@ import hudson.remoting.RemoteOutputStream;
import hudson.remoting.VirtualChannel;
import hudson.remoting.RemoteInputStream;
import hudson.util.DirScanner;
import hudson.util.FileVisitor;
import hudson.util.IOException2;
import hudson.util.HeadBufferingStream;
import hudson.util.FormValidation;
......@@ -48,16 +47,15 @@ import static hudson.util.jna.GNUCLibrary.LIBC;
import static hudson.Util.fixEmpty;
import static hudson.FilePath.TarCompression.GZIP;
import hudson.os.PosixAPI;
import hudson.org.apache.tools.tar.TarOutputStream;
import hudson.org.apache.tools.tar.TarInputStream;
import hudson.util.io.Archiver;
import hudson.util.io.ArchiverFactory;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.commons.io.input.CountingInputStream;
import org.apache.commons.fileupload.FileItem;
import org.kohsuke.stapler.Stapler;
......@@ -78,7 +76,6 @@ import java.io.OutputStream;
import java.io.Serializable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.Closeable;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
......@@ -335,7 +332,7 @@ public final class FilePath implements Serializable {
* @since 1.315
*/
public void zip(OutputStream os, FileFilter filter) throws IOException, InterruptedException {
archive(new ZipArchiverFactory(),os,filter);
archive(ArchiverFactory.ZIP,os,filter);
}
/**
......@@ -350,7 +347,7 @@ public final class FilePath implements Serializable {
* Use {@link #zip(OutputStream,String)} that has more consistent name.
*/
public void createZipArchive(OutputStream os, final String glob) throws IOException, InterruptedException {
archive(new ZipArchiverFactory(),os,glob);
archive(ArchiverFactory.ZIP,os,glob);
}
/**
......@@ -363,14 +360,14 @@ public final class FilePath implements Serializable {
* @since 1.315
*/
public void zip(OutputStream os, final String glob) throws IOException, InterruptedException {
archive(new ZipArchiverFactory(),os,glob);
archive(ArchiverFactory.ZIP,os,glob);
}
/**
* Uses the given scanner on 'this' directory to list up files and then archive it to a zip stream.
*/
public int zip(OutputStream out, DirScanner scanner) throws IOException, InterruptedException {
return archive(new ZipArchiverFactory(), out, scanner);
return archive(ArchiverFactory.ZIP, out, scanner);
}
/**
......@@ -1512,132 +1509,6 @@ public final class FilePath implements Serializable {
}
}
private static interface ArchiverFactory extends Serializable {
Archiver create(OutputStream out);
}
private static final class TarArchiverFactory implements ArchiverFactory, Serializable {
public Archiver create(OutputStream out) {
return new TarWriter(out);
}
private static final long serialVersionUID = 1L;
}
private static final class ZipArchiverFactory implements ArchiverFactory, Serializable {
public Archiver create(OutputStream out) {
return new ZipWriter(out);
}
private static final long serialVersionUID = 1L;
}
/**
* Base for {@link TarWriter} and {@link ZipWriter}.
*/
private static abstract class Archiver extends FileVisitor implements Closeable {
protected int entriesWritten =0;
/**
* Number of files/directories archived.
*/
public int countEntries() {
return entriesWritten;
}
}
/**
* {@link FileVisitor} that creates a tar archive.
*/
private static final class TarWriter extends Archiver {
private final byte[] buf = new byte[8192];
private final TarOutputStream tar;
private TarWriter(OutputStream 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.
@Override
public void flush() throws IOException {
// so don't do anything in flush
}
});
tar.setLongFileMode(TarOutputStream.LONGFILE_GNU);
}
public void visit(File file, String relativePath) throws IOException {
if(Functions.isWindows())
relativePath = relativePath.replace('\\','/');
if(file.isDirectory())
relativePath+='/';
TarEntry te = new TarEntry(relativePath);
te.setModTime(file.lastModified());
if(!file.isDirectory())
te.setSize(file.length());
tar.putNextEntry(te);
if (!file.isDirectory()) {
FileInputStream in = new FileInputStream(file);
try {
int len;
while((len=in.read(buf))>=0)
tar.write(buf,0,len);
} finally {
in.close();
}
}
tar.closeEntry();
entriesWritten++;
}
public void close() throws IOException {
tar.close();
}
}
/**
* {@link FileVisitor} that creates a zip archive.
*/
private static final class ZipWriter extends Archiver {
private final byte[] buf = new byte[8192];
private final ZipOutputStream zip;
private ZipWriter(OutputStream out) {
zip = new ZipOutputStream(out);
zip.setEncoding(System.getProperty("file.encoding"));
}
public void visit(File f, String relativePath) throws IOException {
if(f.isDirectory()) {
ZipEntry dirZipEntry = new ZipEntry(relativePath+'/');
// Setting this bit explicitly is needed by some unzipping applications (see HUDSON-3294).
dirZipEntry.setExternalAttributes(BITMASK_IS_DIRECTORY);
zip.putNextEntry(dirZipEntry);
zip.closeEntry();
} else {
zip.putNextEntry(new ZipEntry(relativePath));
FileInputStream in = new FileInputStream(f);
int len;
while((len=in.read(buf))>0)
zip.write(buf,0,len);
in.close();
zip.closeEntry();
}
entriesWritten++;
}
public void close() throws IOException {
zip.close();
}
// Bitmask indicating directories in 'external attributes' of a ZIP archive entry.
private static final long BITMASK_IS_DIRECTORY = 1<<4;
}
/**
* Writes files in 'this' directory to a tar stream.
......@@ -1646,18 +1517,18 @@ public final class FilePath implements Serializable {
* Ant file pattern mask, like "**&#x2F;*.java".
*/
public int tar(OutputStream out, final String glob) throws IOException, InterruptedException {
return archive(new TarArchiverFactory(), out, glob);
return archive(ArchiverFactory.TAR, out, glob);
}
public int tar(OutputStream out, FileFilter filter) throws IOException, InterruptedException {
return archive(new TarArchiverFactory(), out, filter);
return archive(ArchiverFactory.TAR, out, filter);
}
/**
* Uses the given scanner on 'this' directory to list up files and then archive it to a tar stream.
*/
public int tar(OutputStream out, DirScanner scanner) throws IOException, InterruptedException {
return archive(new TarArchiverFactory(), out, scanner);
return archive(ArchiverFactory.TAR, out, scanner);
}
/**
......@@ -1667,13 +1538,13 @@ public final class FilePath implements Serializable {
* number of files/directories that are written.
*/
private Integer writeToTar(File baseDir, String fileMask, String excludes, OutputStream out) throws IOException {
TarWriter tw = new TarWriter(out);
Archiver tw = ArchiverFactory.TAR.create(out);
try {
new DirScanner.Glob(fileMask,excludes).scan(baseDir,tw);
} finally {
tw.close();
}
return tw.entriesWritten;
return tw.countEntries();
}
/**
......
......@@ -7,7 +7,7 @@ import java.io.Serializable;
/**
* Visits files in a directory recursively.
*
* @since 1.343
* @see DirScanner
*/
......
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.util.io;
import hudson.util.FileVisitor;
import java.io.Closeable;
/**
* {@link FileVisitor} that creates archive files.
*
* @since 1.359
* @see ArchiverFactory
*/
public abstract class Archiver extends FileVisitor implements Closeable {
protected int entriesWritten =0;
/**
* Number of files/directories archived.
*/
public int countEntries() {
return entriesWritten;
}
}
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.util.io;
import hudson.FilePath.TarCompression;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
/**
* Creates {@link Archiver} on top of a stream.
*
* @author Kohsuke Kawaguchi
* @since 1.359
*/
public abstract class ArchiverFactory implements Serializable {
/**
* Creates an archiver on top of the given stream.
*/
public abstract Archiver create(OutputStream out) throws IOException;
/**
* Uncompressed tar format.
*/
public static ArchiverFactory TAR = new TarArchiverFactory(TarCompression.NONE);
/**
* tar+gz
*/
public static ArchiverFactory TARGZ = new TarArchiverFactory(TarCompression.GZIP);
/**
* Zip format.
*/
public static ArchiverFactory ZIP = new ZipArchiverFactory();
private static final class TarArchiverFactory extends ArchiverFactory {
private final TarCompression method;
private TarArchiverFactory(TarCompression method) {
this.method = method;
}
public Archiver create(OutputStream out) throws IOException {
return new TarArchiver(method.compress(out));
}
private static final long serialVersionUID = 1L;
}
private static final class ZipArchiverFactory extends ArchiverFactory {
public Archiver create(OutputStream out) {
return new ZipArchiver(out);
}
private static final long serialVersionUID = 1L;
}
private static final long serialVersionUID = 1L;
}
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.util.io;
import hudson.Functions;
import hudson.org.apache.tools.tar.TarOutputStream;
import hudson.util.FileVisitor;
import org.apache.tools.tar.TarEntry;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* {@link FileVisitor} that creates a tar archive.
*
* @see ArchiverFactory#TAR
*/
final class TarArchiver extends Archiver {
private final byte[] buf = new byte[8192];
private final TarOutputStream tar;
TarArchiver(OutputStream 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.
@Override
public void flush() throws IOException {
// so don't do anything in flush
}
});
tar.setLongFileMode(TarOutputStream.LONGFILE_GNU);
}
public void visit(File file, String relativePath) throws IOException {
if(Functions.isWindows())
relativePath = relativePath.replace('\\','/');
if(file.isDirectory())
relativePath+='/';
TarEntry te = new TarEntry(relativePath);
te.setModTime(file.lastModified());
if(!file.isDirectory())
te.setSize(file.length());
tar.putNextEntry(te);
if (!file.isDirectory()) {
FileInputStream in = new FileInputStream(file);
try {
int len;
while((len=in.read(buf))>=0)
tar.write(buf,0,len);
} finally {
in.close();
}
}
tar.closeEntry();
entriesWritten++;
}
public void close() throws IOException {
tar.close();
}
}
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.util.io;
import hudson.util.FileVisitor;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* {@link FileVisitor} that creates a zip archive.
*
* @see ArchiverFactory#ZIP
*/
final class ZipArchiver extends Archiver {
private final byte[] buf = new byte[8192];
private final ZipOutputStream zip;
ZipArchiver(OutputStream out) {
zip = new ZipOutputStream(out);
zip.setEncoding(System.getProperty("file.encoding"));
}
public void visit(File f, String relativePath) throws IOException {
if(f.isDirectory()) {
ZipEntry dirZipEntry = new ZipEntry(relativePath+'/');
// Setting this bit explicitly is needed by some unzipping applications (see HUDSON-3294).
dirZipEntry.setExternalAttributes(BITMASK_IS_DIRECTORY);
zip.putNextEntry(dirZipEntry);
zip.closeEntry();
} else {
zip.putNextEntry(new ZipEntry(relativePath));
FileInputStream in = new FileInputStream(f);
int len;
while((len=in.read(buf))>0)
zip.write(buf,0,len);
in.close();
zip.closeEntry();
}
entriesWritten++;
}
public void close() throws IOException {
zip.close();
}
// Bitmask indicating directories in 'external attributes' of a ZIP archive entry.
private static final long BITMASK_IS_DIRECTORY = 1<<4;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册