diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Tar.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Tar.java | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Tar.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Tar.java new file mode 100644 index 00000000..97547022 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Tar.java @@ -0,0 +1,1016 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; +import java.util.zip.GZIPOutputStream; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.ArchiveFileSet; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.types.resources.ArchiveResource; +import org.apache.tools.ant.types.resources.FileProvider; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.types.resources.TarResource; +import org.apache.tools.ant.types.selectors.SelectorUtils; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.MergingMapper; +import org.apache.tools.ant.util.ResourceUtils; +import org.apache.tools.ant.util.SourceFileScanner; +import org.apache.tools.bzip2.CBZip2OutputStream; +import org.apache.tools.tar.TarConstants; +import org.apache.tools.tar.TarEntry; +import org.apache.tools.tar.TarOutputStream; + +/** + * Creates a tar archive. + * + * @since Ant 1.1 + * + * @ant.task category="packaging" + */ +public class Tar extends MatchingTask { + private static final int BUFFER_SIZE = 8 * 1024; + + /** + * @deprecated since 1.5.x. + * Tar.WARN is deprecated and is replaced with + * Tar.TarLongFileMode.WARN + */ + @Deprecated + public static final String WARN = "warn"; + /** + * @deprecated since 1.5.x. + * Tar.FAIL is deprecated and is replaced with + * Tar.TarLongFileMode.FAIL + */ + @Deprecated + public static final String FAIL = "fail"; + /** + * @deprecated since 1.5.x. + * Tar.TRUNCATE is deprecated and is replaced with + * Tar.TarLongFileMode.TRUNCATE + */ + @Deprecated + public static final String TRUNCATE = "truncate"; + /** + * @deprecated since 1.5.x. + * Tar.GNU is deprecated and is replaced with + * Tar.TarLongFileMode.GNU + */ + @Deprecated + public static final String GNU = "gnu"; + /** + * @deprecated since 1.5.x. + * Tar.OMIT is deprecated and is replaced with + * Tar.TarLongFileMode.OMIT + */ + @Deprecated + public static final String OMIT = "omit"; + + // CheckStyle:VisibilityModifier OFF - bc + File tarFile; + File baseDir; + + private TarLongFileMode longFileMode = new TarLongFileMode(); + + // need to keep the package private version for backwards compatibility + Vector<TarFileSet> filesets = new Vector<TarFileSet>(); + // we must keep two lists since other classes may modify the + // filesets Vector (it is package private) without us noticing + private final Vector<ResourceCollection> resourceCollections = new Vector<ResourceCollection>(); + + // CheckStyle:VisibilityModifier ON + + /** + * Indicates whether the user has been warned about long files already. + */ + private boolean longWarningGiven = false; + + private TarCompressionMethod compression = new TarCompressionMethod(); + + /** + * Encoding to use for filenames, defaults to the platform's + * default encoding. + */ + private String encoding; + + /** + * Add a new fileset with the option to specify permissions + * @return the tar fileset to be used as the nested element. + */ + public TarFileSet createTarFileSet() { + final TarFileSet fs = new TarFileSet(); + fs.setProject(getProject()); + filesets.addElement(fs); + return fs; + } + + /** + * Add a collection of resources to archive. + * @param res a resource collection to archive. + * @since Ant 1.7 + */ + public void add(final ResourceCollection res) { + resourceCollections.add(res); + } + + /** + * Set is the name/location of where to create the tar file. + * @param tarFile the location of the tar file. + * @deprecated since 1.5.x. + * For consistency with other tasks, please use setDestFile(). + */ + @Deprecated + public void setTarfile(final File tarFile) { + this.tarFile = tarFile; + } + + /** + * Set is the name/location of where to create the tar file. + * @since Ant 1.5 + * @param destFile The output of the tar + */ + public void setDestFile(final File destFile) { + this.tarFile = destFile; + } + + /** + * This is the base directory to look in for things to tar. + * @param baseDir the base directory. + */ + public void setBasedir(final File baseDir) { + this.baseDir = baseDir; + } + + /** + * Set how to handle long files, those with a path>100 chars. + * Optional, default=warn. + * <p> + * Allowable values are + * <ul> + * <li> truncate - paths are truncated to the maximum length + * <li> fail - paths greater than the maximum cause a build exception + * <li> warn - paths greater than the maximum cause a warning and GNU is used + * <li> gnu - GNU extensions are used for any paths greater than the maximum. + * <li> omit - paths greater than the maximum are omitted from the archive + * </ul> + * @param mode the mode string to handle long files. + * @deprecated since 1.5.x. + * setLongFile(String) is deprecated and is replaced with + * setLongFile(Tar.TarLongFileMode) to make Ant's Introspection + * mechanism do the work and also to encapsulate operations on + * the mode in its own class. + */ + @Deprecated + public void setLongfile(final String mode) { + log("DEPRECATED - The setLongfile(String) method has been deprecated." + + " Use setLongfile(Tar.TarLongFileMode) instead."); + this.longFileMode = new TarLongFileMode(); + longFileMode.setValue(mode); + } + + /** + * Set how to handle long files, those with a path>100 chars. + * Optional, default=warn. + * <p> + * Allowable values are + * <ul> + * <li> truncate - paths are truncated to the maximum length + * <li> fail - paths greater than the maximum cause a build exception + * <li> warn - paths greater than the maximum cause a warning and GNU is used + * <li> gnu - extensions used by older versions of GNU tar are used for any paths greater than the maximum. + * <li> posix - use POSIX PAX extension headers for any paths greater than the maximum. Supported by all modern tar implementations. + * <li> omit - paths greater than the maximum are omitted from the archive + * </ul> + * @param mode the mode to handle long file names. + */ + public void setLongfile(final TarLongFileMode mode) { + this.longFileMode = mode; + } + + /** + * Set compression method. + * Allowable values are + * <ul> + * <li> none - no compression + * <li> gzip - Gzip compression + * <li> bzip2 - Bzip2 compression + * </ul> + * @param mode the compression method. + */ + public void setCompression(final TarCompressionMethod mode) { + this.compression = mode; + } + + /** + * Encoding to use for filenames, defaults to the platform's + * default encoding. + * + * <p>For a list of possible values see <a + * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.</p> + * @param encoding the encoding name + * + * @since Ant 1.9.5 + */ + public void setEncoding(final String encoding) { + this.encoding = encoding; + } + + /** + * do the business + * @throws BuildException on error + */ + @Override + public void execute() throws BuildException { + if (tarFile == null) { + throw new BuildException("tarfile attribute must be set!", + getLocation()); + } + + if (tarFile.exists() && tarFile.isDirectory()) { + throw new BuildException("tarfile is a directory!", + getLocation()); + } + + if (tarFile.exists() && !tarFile.canWrite()) { + throw new BuildException("Can not write to the specified tarfile!", + getLocation()); + } + + @SuppressWarnings("unchecked") + final Vector<TarFileSet> savedFileSets = (Vector<TarFileSet>) filesets.clone(); + try { + if (baseDir != null) { + if (!baseDir.exists()) { + throw new BuildException("basedir does not exist!", + getLocation()); + } + + // add the main fileset to the list of filesets to process. + final TarFileSet mainFileSet = new TarFileSet(fileset); + mainFileSet.setDir(baseDir); + filesets.addElement(mainFileSet); + } + + if (filesets.size() == 0 && resourceCollections.size() == 0) { + throw new BuildException("You must supply either a basedir " + + "attribute or some nested resource" + + " collections.", + getLocation()); + } + + // check if tar is out of date with respect to each + // fileset + boolean upToDate = true; + for(final TarFileSet tfs : filesets) { + upToDate &= check(tfs); + } + for(final ResourceCollection rcol : resourceCollections) { + upToDate &= check(rcol); + } + + if (upToDate) { + log("Nothing to do: " + tarFile.getAbsolutePath() + + " is up to date.", Project.MSG_INFO); + return; + } + + final File parent = tarFile.getParentFile(); + if (parent != null && !parent.isDirectory() + && !(parent.mkdirs() || parent.isDirectory())) { + throw new BuildException("Failed to create missing parent" + + " directory for " + tarFile); + } + + log("Building tar: " + tarFile.getAbsolutePath(), Project.MSG_INFO); + + TarOutputStream tOut = null; + try { + tOut = new TarOutputStream( + compression.compress( + new BufferedOutputStream( + new FileOutputStream(tarFile))), + encoding); + tOut.setDebug(true); + if (longFileMode.isTruncateMode()) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE); + } else if (longFileMode.isFailMode() + || longFileMode.isOmitMode()) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_ERROR); + } else if (longFileMode.isPosixMode()) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_POSIX); + } else { + // warn or GNU + tOut.setLongFileMode(TarOutputStream.LONGFILE_GNU); + } + + longWarningGiven = false; + for (final TarFileSet tfs : filesets) { + tar(tfs, tOut); + } + for (final ResourceCollection rcol : resourceCollections) { + tar(rcol, tOut); + } + } catch (final IOException ioe) { + final String msg = "Problem creating TAR: " + ioe.getMessage(); + throw new BuildException(msg, ioe, getLocation()); + } finally { + FileUtils.close(tOut); + } + } finally { + filesets = savedFileSets; + } + } + + /** + * tar a file + * @param file the file to tar + * @param tOut the output stream + * @param vPath the path name of the file to tar + * @param tarFileSet the fileset that the file came from. + * @throws IOException on error + */ + protected void tarFile(final File file, final TarOutputStream tOut, final String vPath, + final TarFileSet tarFileSet) + throws IOException { + if (file.equals(tarFile)) { + // If the archive is built for the first time and it is + // matched by a resource collection, then it hasn't been + // found in check (it hasn't been there) but will be + // included now. + // + // for some strange reason the old code would simply skip + // the entry and not fail, do the same now for backwards + // compatibility reasons. Without this, the which4j build + // fails in Gump + return; + } + tarResource(new FileResource(file), tOut, vPath, tarFileSet); + } + + /** + * tar a resource + * @param r the resource to tar + * @param tOut the output stream + * @param vPath the path name of the file to tar + * @param tarFileSet the fileset that the file came from, may be null. + * @throws IOException on error + * @since Ant 1.7 + */ + protected void tarResource(final Resource r, final TarOutputStream tOut, String vPath, + final TarFileSet tarFileSet) + throws IOException { + + if (!r.isExists()) { + return; + } + + boolean preserveLeadingSlashes = false; + + if (tarFileSet != null) { + final String fullpath = tarFileSet.getFullpath(this.getProject()); + if (fullpath.length() > 0) { + vPath = fullpath; + } else { + // don't add "" to the archive + if (vPath.length() <= 0) { + return; + } + + String prefix = tarFileSet.getPrefix(this.getProject()); + // '/' is appended for compatibility with the zip task. + if (prefix.length() > 0 && !prefix.endsWith("/")) { + prefix = prefix + "/"; + } + vPath = prefix + vPath; + } + + preserveLeadingSlashes = tarFileSet.getPreserveLeadingSlashes(); + + if (vPath.startsWith("/") && !preserveLeadingSlashes) { + final int l = vPath.length(); + if (l <= 1) { + // we would end up adding "" to the archive + return; + } + vPath = vPath.substring(1, l); + } + } + + if (r.isDirectory() && !vPath.endsWith("/")) { + vPath += "/"; + } + + if (vPath.length() >= TarConstants.NAMELEN) { + if (longFileMode.isOmitMode()) { + log("Omitting: " + vPath, Project.MSG_INFO); + return; + } else if (longFileMode.isWarnMode()) { + log("Entry: " + vPath + " longer than " + + TarConstants.NAMELEN + " characters.", + Project.MSG_WARN); + if (!longWarningGiven) { + log("Resulting tar file can only be processed " + + "successfully by GNU compatible tar commands", + Project.MSG_WARN); + longWarningGiven = true; + } + } else if (longFileMode.isFailMode()) { + throw new BuildException("Entry: " + vPath + + " longer than " + TarConstants.NAMELEN + + "characters.", getLocation()); + } + } + + final TarEntry te = new TarEntry(vPath, preserveLeadingSlashes); + te.setModTime(r.getLastModified()); + // preserve permissions + if (r instanceof ArchiveResource) { + final ArchiveResource ar = (ArchiveResource) r; + te.setMode(ar.getMode()); + if (r instanceof TarResource) { + final TarResource tr = (TarResource) r; + te.setUserName(tr.getUserName()); + te.setUserId(tr.getUid()); + te.setGroupName(tr.getGroup()); + te.setGroupId(tr.getGid()); + } + } + + if (!r.isDirectory()) { + if (r.size() > TarConstants.MAXSIZE) { + throw new BuildException( + "Resource: " + r + " larger than " + + TarConstants.MAXSIZE + " bytes."); + } + te.setSize(r.getSize()); + // override permissions if set explicitly + if (tarFileSet != null && tarFileSet.hasFileModeBeenSet()) { + te.setMode(tarFileSet.getMode()); + } + } else if (tarFileSet != null && tarFileSet.hasDirModeBeenSet()) { + // override permissions if set explicitly + te.setMode(tarFileSet.getDirMode(this.getProject())); + } + + if (tarFileSet != null) { + // only override permissions if set explicitly + if (tarFileSet.hasUserNameBeenSet()) { + te.setUserName(tarFileSet.getUserName()); + } + if (tarFileSet.hasGroupBeenSet()) { + te.setGroupName(tarFileSet.getGroup()); + } + if (tarFileSet.hasUserIdBeenSet()) { + te.setUserId(tarFileSet.getUid()); + } + if (tarFileSet.hasGroupIdBeenSet()) { + te.setGroupId(tarFileSet.getGid()); + } + } + + InputStream in = null; + try { + tOut.putNextEntry(te); + + if (!r.isDirectory()) { + in = r.getInputStream(); + + final byte[] buffer = new byte[BUFFER_SIZE]; + int count = 0; + do { + tOut.write(buffer, 0, count); + count = in.read(buffer, 0, buffer.length); + } while (count != -1); + } + + tOut.closeEntry(); + } finally { + FileUtils.close(in); + } + } + + /** + * Is the archive up to date in relationship to a list of files. + * @param files the files to check + * @return true if the archive is up to date. + * @deprecated since 1.5.x. + * use the two-arg version instead. + */ + @Deprecated + protected boolean archiveIsUpToDate(final String[] files) { + return archiveIsUpToDate(files, baseDir); + } + + /** + * Is the archive up to date in relationship to a list of files. + * @param files the files to check + * @param dir the base directory for the files. + * @return true if the archive is up to date. + * @since Ant 1.5.2 + */ + protected boolean archiveIsUpToDate(final String[] files, final File dir) { + final SourceFileScanner sfs = new SourceFileScanner(this); + final MergingMapper mm = new MergingMapper(); + mm.setTo(tarFile.getAbsolutePath()); + return sfs.restrict(files, dir, null, mm).length == 0; + } + + /** + * Is the archive up to date in relationship to a list of files. + * @param r the files to check + * @return true if the archive is up to date. + * @since Ant 1.7 + */ + protected boolean archiveIsUpToDate(final Resource r) { + return SelectorUtils.isOutOfDate(new FileResource(tarFile), r, + FileUtils.getFileUtils() + .getFileTimestampGranularity()); + } + + /** + * Whether this task can deal with non-file resources. + * + * <p>This implementation returns true only if this task is + * <tar>. Any subclass of this class that also wants to + * support non-file resources needs to override this method. We + * need to do so for backwards compatibility reasons since we + * can't expect subclasses to support resources.</p> + * @return true for this task. + * @since Ant 1.7 + */ + protected boolean supportsNonFileResources() { + return getClass().equals(Tar.class); + } + + /** + * Checks whether the archive is out-of-date with respect to the resources + * of the given collection. + * + * <p>Also checks that either all collections only contain file + * resources or this class supports non-file collections.</p> + * + * <p>And - in case of file-collections - ensures that the archive won't + * contain itself.</p> + * + * @param rc the resource collection to check + * @return whether the archive is up-to-date + * @since Ant 1.7 + */ + protected boolean check(final ResourceCollection rc) { + boolean upToDate = true; + if (isFileFileSet(rc)) { + final FileSet fs = (FileSet) rc; + upToDate = check(fs.getDir(getProject()), getFileNames(fs)); + } else if (!rc.isFilesystemOnly() && !supportsNonFileResources()) { + throw new BuildException("only filesystem resources are supported"); + } else if (rc.isFilesystemOnly()) { + final Set<File> basedirs = new HashSet<File>(); + final Map<File, List<String>> basedirToFilesMap = new HashMap<File, List<String>>(); + for (final Resource res : rc) { + final FileResource r = ResourceUtils + .asFileResource(res.as(FileProvider.class)); + File base = r.getBaseDir(); + if (base == null) { + base = Copy.NULL_FILE_PLACEHOLDER; + } + basedirs.add(base); + List<String> files = basedirToFilesMap.get(base); + if (files == null) { + files = new Vector<String>(); + basedirToFilesMap.put(base, files); + } + if (base == Copy.NULL_FILE_PLACEHOLDER) { + files.add(r.getFile().getAbsolutePath()); + } else { + files.add(r.getName()); + } + } + for (final File base : basedirs) { + final File tmpBase = base == Copy.NULL_FILE_PLACEHOLDER ? null : base; + final List<String> files = basedirToFilesMap.get(base); + upToDate &= check(tmpBase, files); + } + } else { // non-file resources + final Iterator<Resource> iter = rc.iterator(); + while (upToDate && iter.hasNext()) { + final Resource r = iter.next(); + upToDate = archiveIsUpToDate(r); + } + } + return upToDate; + } + + /** + * <p>Checks whether the archive is out-of-date with respect to the + * given files, ensures that the archive won't contain itself.</p> + * + * @param basedir base directory for file names + * @param files array of relative file names + * @return whether the archive is up-to-date + * @since Ant 1.7 + */ + protected boolean check(final File basedir, final String[] files) { + boolean upToDate = true; + if (!archiveIsUpToDate(files, basedir)) { + upToDate = false; + } + + for (int i = 0; i < files.length; ++i) { + if (tarFile.equals(new File(basedir, files[i]))) { + throw new BuildException("A tar file cannot include " + + "itself", getLocation()); + } + } + return upToDate; + } + + /** + * <p>Checks whether the archive is out-of-date with respect to the + * given files, ensures that the archive won't contain itself.</p> + * + * @param basedir base directory for file names + * @param files array of relative file names + * @return whether the archive is up-to-date + * @see #check(File, String[]) + * @since Ant 1.9.5 + */ + protected boolean check(final File basedir, final Collection<String> files) { + return check(basedir, files.toArray(new String[files.size()])); + } + + /** + * Adds the resources contained in this collection to the archive. + * + * <p>Uses the file based methods for file resources for backwards + * compatibility.</p> + * + * @param rc the collection containing resources to add + * @param tOut stream writing to the archive. + * @throws IOException on error. + * @since Ant 1.7 + */ + protected void tar(final ResourceCollection rc, final TarOutputStream tOut) + throws IOException { + ArchiveFileSet afs = null; + if (rc instanceof ArchiveFileSet) { + afs = (ArchiveFileSet) rc; + } + if (afs != null && afs.size() > 1 + && afs.getFullpath(this.getProject()).length() > 0) { + throw new BuildException("fullpath attribute may only " + + "be specified for " + + "filesets that specify a " + + "single file."); + } + final TarFileSet tfs = asTarFileSet(afs); + + if (isFileFileSet(rc)) { + final FileSet fs = (FileSet) rc; + final String[] files = getFileNames(fs); + for (int i = 0; i < files.length; i++) { + final File f = new File(fs.getDir(getProject()), files[i]); + final String name = files[i].replace(File.separatorChar, '/'); + tarFile(f, tOut, name, tfs); + } + } else if (rc.isFilesystemOnly()) { + for (final Resource r : rc) { + final File f = r.as(FileProvider.class).getFile(); + tarFile(f, tOut, f.getName(), tfs); + } + } else { // non-file resources + for (final Resource r : rc) { + tarResource(r, tOut, r.getName(), tfs); + } + } + } + + /** + * whether the given resource collection is a (subclass of) + * FileSet that only contains file system resources. + * @param rc the resource collection to check. + * @return true if the collection is a fileset. + * @since Ant 1.7 + */ + protected static boolean isFileFileSet(final ResourceCollection rc) { + return rc instanceof FileSet && rc.isFilesystemOnly(); + } + + /** + * Grabs all included files and directors from the FileSet and + * returns them as an array of (relative) file names. + * @param fs the fileset to operate on. + * @return a list of the filenames. + * @since Ant 1.7 + */ + protected static String[] getFileNames(final FileSet fs) { + final DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject()); + final String[] directories = ds.getIncludedDirectories(); + final String[] filesPerSe = ds.getIncludedFiles(); + final String[] files = new String [directories.length + filesPerSe.length]; + System.arraycopy(directories, 0, files, 0, directories.length); + System.arraycopy(filesPerSe, 0, files, directories.length, + filesPerSe.length); + return files; + } + + /** + * Copies fullpath, prefix and permission attributes from the + * ArchiveFileSet to a new TarFileSet (or returns it unchanged if + * it already is a TarFileSet). + * + * @param archiveFileSet fileset to copy attributes from, may be null + * @return a new TarFileSet. + * @since Ant 1.7 + */ + protected TarFileSet asTarFileSet(final ArchiveFileSet archiveFileSet) { + TarFileSet tfs = null; + if (archiveFileSet != null && archiveFileSet instanceof TarFileSet) { + tfs = (TarFileSet) archiveFileSet; + } else { + tfs = new TarFileSet(); + tfs.setProject(getProject()); + if (archiveFileSet != null) { + tfs.setPrefix(archiveFileSet.getPrefix(getProject())); + tfs.setFullpath(archiveFileSet.getFullpath(getProject())); + if (archiveFileSet.hasFileModeBeenSet()) { + tfs.integerSetFileMode(archiveFileSet + .getFileMode(getProject())); + } + if (archiveFileSet.hasDirModeBeenSet()) { + tfs.integerSetDirMode(archiveFileSet + .getDirMode(getProject())); + } + + if (archiveFileSet + instanceof org.apache.tools.ant.types.TarFileSet) { + final org.apache.tools.ant.types.TarFileSet t = + (org.apache.tools.ant.types.TarFileSet) archiveFileSet; + if (t.hasUserNameBeenSet()) { + tfs.setUserName(t.getUserName()); + } + if (t.hasGroupBeenSet()) { + tfs.setGroup(t.getGroup()); + } + if (t.hasUserIdBeenSet()) { + tfs.setUid(t.getUid()); + } + if (t.hasGroupIdBeenSet()) { + tfs.setGid(t.getGid()); + } + } + } + } + return tfs; + } + + /** + * This is a FileSet with the option to specify permissions + * and other attributes. + */ + public static class TarFileSet + extends org.apache.tools.ant.types.TarFileSet { + private String[] files = null; + + private boolean preserveLeadingSlashes = false; + + /** + * Creates a new <code>TarFileSet</code> instance. + * Using a fileset as a constructor argument. + * + * @param fileset a <code>FileSet</code> value + */ + public TarFileSet(final FileSet fileset) { + super(fileset); + } + + /** + * Creates a new <code>TarFileSet</code> instance. + * + */ + public TarFileSet() { + super(); + } + + /** + * Get a list of files and directories specified in the fileset. + * @param p the current project. + * @return a list of file and directory names, relative to + * the baseDir for the project. + */ + public String[] getFiles(final Project p) { + if (files == null) { + files = getFileNames(this); + } + + return files; + } + + /** + * A 3 digit octal string, specify the user, group and + * other modes in the standard Unix fashion; + * optional, default=0644 + * @param octalString a 3 digit octal string. + */ + public void setMode(final String octalString) { + setFileMode(octalString); + } + + /** + * @return the current mode. + */ + public int getMode() { + return getFileMode(this.getProject()); + } + + /** + * Flag to indicates whether leading `/'s should + * be preserved in the file names. + * Optional, default is <code>false</code>. + * @param b the leading slashes flag. + */ + public void setPreserveLeadingSlashes(final boolean b) { + this.preserveLeadingSlashes = b; + } + + /** + * @return the leading slashes flag. + */ + public boolean getPreserveLeadingSlashes() { + return preserveLeadingSlashes; + } + } + + /** + * Set of options for long file handling in the task. + * + */ + public static class TarLongFileMode extends EnumeratedAttribute { + + /** permissible values for longfile attribute */ + public static final String + WARN = "warn", + FAIL = "fail", + TRUNCATE = "truncate", + GNU = "gnu", + POSIX = "posix", + OMIT = "omit"; + + private final String[] validModes = { + WARN, FAIL, TRUNCATE, GNU, POSIX, OMIT + }; + + /** Constructor, defaults to "warn" */ + public TarLongFileMode() { + super(); + setValue(WARN); + } + + /** + * @return the possible values for this enumerated type. + */ + @Override + public String[] getValues() { + return validModes; + } + + /** + * @return true if value is "truncate". + */ + public boolean isTruncateMode() { + return TRUNCATE.equalsIgnoreCase(getValue()); + } + + /** + * @return true if value is "warn". + */ + public boolean isWarnMode() { + return WARN.equalsIgnoreCase(getValue()); + } + + /** + * @return true if value is "gnu". + */ + public boolean isGnuMode() { + return GNU.equalsIgnoreCase(getValue()); + } + + /** + * @return true if value is "fail". + */ + public boolean isFailMode() { + return FAIL.equalsIgnoreCase(getValue()); + } + + /** + * @return true if value is "omit". + */ + public boolean isOmitMode() { + return OMIT.equalsIgnoreCase(getValue()); + } + + /** + * @return true if value is "posix". + */ + public boolean isPosixMode() { + return POSIX.equalsIgnoreCase(getValue()); + } + } + + /** + * Valid Modes for Compression attribute to Tar Task + * + */ + public static final class TarCompressionMethod extends EnumeratedAttribute { + + // permissible values for compression attribute + /** + * No compression + */ + private static final String NONE = "none"; + /** + * GZIP compression + */ + private static final String GZIP = "gzip"; + /** + * BZIP2 compression + */ + private static final String BZIP2 = "bzip2"; + + + /** + * Default constructor + */ + public TarCompressionMethod() { + super(); + setValue(NONE); + } + + /** + * Get valid enumeration values. + * @return valid enumeration values + */ + @Override + public String[] getValues() { + return new String[] {NONE, GZIP, BZIP2 }; + } + + /** + * This method wraps the output stream with the + * corresponding compression method + * + * @param ostream output stream + * @return output stream with on-the-fly compression + * @exception IOException thrown if file is not writable + */ + private OutputStream compress(final OutputStream ostream) + throws IOException { + final String v = getValue(); + if (GZIP.equals(v)) { + return new GZIPOutputStream(ostream); + } else { + if (BZIP2.equals(v)) { + ostream.write('B'); + ostream.write('Z'); + return new CBZip2OutputStream(ostream); + } + } + return ostream; + } + } +} |