FileDocCategorySizeDatePackage
Tar.javaAPI DocApache Ant 1.7033411Wed Dec 13 06:16:24 GMT 2006org.apache.tools.ant.taskdefs

Tar

public class Tar extends MatchingTask
Creates a tar archive.
since
Ant 1.1
ant.task
category="packaging"

Fields Summary
public static final String
WARN
public static final String
FAIL
public static final String
TRUNCATE
public static final String
GNU
public static final String
OMIT
File
tarFile
File
baseDir
private TarLongFileMode
longFileMode
Vector
filesets
private Vector
resourceCollections
Vector
fileSetFiles
private boolean
longWarningGiven
Indicates whether the user has been warned about long files already.
private TarCompressionMethod
compression
Constructors Summary
Methods Summary
public voidadd(org.apache.tools.ant.types.ResourceCollection res)
Add a collection of resources to archive.

param
res a resource collection to archive.
since
Ant 1.7

        resourceCollections.add(res);
    
protected booleanarchiveIsUpToDate(java.lang.String[] files)
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.

        return archiveIsUpToDate(files, baseDir);
    
protected booleanarchiveIsUpToDate(java.lang.String[] files, java.io.File dir)
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

        SourceFileScanner sfs = new SourceFileScanner(this);
        MergingMapper mm = new MergingMapper();
        mm.setTo(tarFile.getAbsolutePath());
        return sfs.restrict(files, dir, null, mm).length == 0;
    
protected booleanarchiveIsUpToDate(org.apache.tools.ant.types.Resource r)
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

        return SelectorUtils.isOutOfDate(new FileResource(tarFile), r,
                                         FileUtils.getFileUtils()
                                         .getFileTimestampGranularity());
    
protected org.apache.tools.ant.taskdefs.Tar$TarFileSetasTarFileSet(org.apache.tools.ant.types.ArchiveFileSet archiveFileSet)
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

        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) {
                    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;
    
protected booleancheck(org.apache.tools.ant.types.ResourceCollection rc)
Checks whether the archive is out-of-date with respect to the resources of the given collection.

Also checks that either all collections only contain file resources or this class supports non-file collections.

And - in case of file-collections - ensures that the archive won't contain itself.

param
rc the resource collection to check
return
whether the archive is up-to-date
since
Ant 1.7

        boolean upToDate = true;
        if (isFileFileSet(rc)) {
            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()) {
            HashSet basedirs = new HashSet();
            HashMap basedirToFilesMap = new HashMap();
            Iterator iter = rc.iterator();
            while (iter.hasNext()) {
                FileResource r = (FileResource) iter.next();
                File base = r.getBaseDir();
                if (base == null) {
                    base = Copy.NULL_FILE_PLACEHOLDER;
                }
                basedirs.add(base);
                Vector files = (Vector) basedirToFilesMap.get(base);
                if (files == null) {
                    files = new Vector();
                    basedirToFilesMap.put(base, new Vector());
                }
                files.add(r.getName());
            }
            iter = basedirs.iterator();
            while (iter.hasNext()) {
                File base = (File) iter.next();
                Vector f = (Vector) basedirToFilesMap.get(base);
                String[] files = (String[]) f.toArray(new String[f.size()]);
                upToDate &=
                    check(base == Copy.NULL_FILE_PLACEHOLDER ? null : base,
                          files);
            }
        } else { // non-file resources
            Iterator iter = rc.iterator();
            while (upToDate && iter.hasNext()) {
                Resource r = (Resource) iter.next();
                upToDate &= archiveIsUpToDate(r);
            }
        }

        return upToDate;
    
protected booleancheck(java.io.File basedir, java.lang.String[] files)
Checks whether the archive is out-of-date with respect to the given files, ensures that the archive won't contain itself.

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

        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;
    
public org.apache.tools.ant.taskdefs.Tar$TarFileSetcreateTarFileSet()
Add a new fileset with the option to specify permissions

return
the tar fileset to be used as the nested element.


                              
       
        TarFileSet fs = new TarFileSet();
        fs.setProject(getProject());
        filesets.addElement(fs);
        return fs;
    
public voidexecute()
do the business

throws
BuildException on error

        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());
        }

        Vector savedFileSets = (Vector) 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.
                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 (Enumeration e = filesets.elements(); e.hasMoreElements();) {
                upToDate &= check((TarFileSet) e.nextElement());
            }
            for (Enumeration e = resourceCollections.elements();
                 e.hasMoreElements();) {
                upToDate &= check((ResourceCollection) e.nextElement());
            }

            if (upToDate) {
                log("Nothing to do: " + tarFile.getAbsolutePath()
                    + " is up to date.", Project.MSG_INFO);
                return;
            }

            log("Building tar: " + tarFile.getAbsolutePath(), Project.MSG_INFO);

            TarOutputStream tOut = null;
            try {
                tOut = new TarOutputStream(
                    compression.compress(
                        new BufferedOutputStream(
                            new FileOutputStream(tarFile))));
                tOut.setDebug(true);
                if (longFileMode.isTruncateMode()) {
                    tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE);
                } else if (longFileMode.isFailMode()
                            || longFileMode.isOmitMode()) {
                    tOut.setLongFileMode(TarOutputStream.LONGFILE_ERROR);
                } else {
                    // warn or GNU
                    tOut.setLongFileMode(TarOutputStream.LONGFILE_GNU);
                }

                longWarningGiven = false;
                for (Enumeration e = filesets.elements();
                     e.hasMoreElements();) {
                    tar((TarFileSet) e.nextElement(), tOut);
                }
                for (Enumeration e = resourceCollections.elements();
                     e.hasMoreElements();) {
                    tar((ResourceCollection) e.nextElement(), tOut);
                }
            } catch (IOException ioe) {
                String msg = "Problem creating TAR: " + ioe.getMessage();
                throw new BuildException(msg, ioe, getLocation());
            } finally {
                FileUtils.close(tOut);
            }
        } finally {
            filesets = savedFileSets;
        }
    
protected static final java.lang.String[]getFileNames(org.apache.tools.ant.types.FileSet fs)
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

        DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject());
        String[] directories = ds.getIncludedDirectories();
        String[] filesPerSe = ds.getIncludedFiles();
        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;
    
protected static final booleanisFileFileSet(org.apache.tools.ant.types.ResourceCollection rc)
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

        return rc instanceof FileSet && rc.isFilesystemOnly();
    
public voidsetBasedir(java.io.File baseDir)
This is the base directory to look in for things to tar.

param
baseDir the base directory.

        this.baseDir = baseDir;
    
public voidsetCompression(org.apache.tools.ant.taskdefs.Tar$TarCompressionMethod mode)
Set compression method. Allowable values are
  • none - no compression
  • gzip - Gzip compression
  • bzip2 - Bzip2 compression

param
mode the compression method.

        this.compression = mode;
    
public voidsetDestFile(java.io.File destFile)
Set is the name/location of where to create the tar file.

since
Ant 1.5
param
destFile The output of the tar

        this.tarFile = destFile;
    
public voidsetLongfile(java.lang.String mode)
Set how to handle long files, those with a path>100 chars. Optional, default=warn.

Allowable values are

  • truncate - paths are truncated to the maximum length
  • fail - paths greater than the maximum cause a build exception
  • warn - paths greater than the maximum cause a warning and GNU is used
  • gnu - GNU extensions are used for any paths greater than the maximum.
  • omit - paths greater than the maximum are omitted from the archive

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.

        log("DEPRECATED - The setLongfile(String) method has been deprecated."
            + " Use setLongfile(Tar.TarLongFileMode) instead.");
        this.longFileMode = new TarLongFileMode();
        longFileMode.setValue(mode);
    
public voidsetLongfile(org.apache.tools.ant.taskdefs.Tar$TarLongFileMode mode)
Set how to handle long files, those with a path>100 chars. Optional, default=warn.

Allowable values are

  • truncate - paths are truncated to the maximum length
  • fail - paths greater than the maximum cause a build exception
  • warn - paths greater than the maximum cause a warning and GNU is used
  • gnu - GNU extensions are used for any paths greater than the maximum.
  • omit - paths greater than the maximum are omitted from the archive

param
mode the mode to handle long file names.

        this.longFileMode = mode;
    
public voidsetTarfile(java.io.File tarFile)
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().

        this.tarFile = tarFile;
    
protected booleansupportsNonFileResources()
Whether this task can deal with non-file resources.

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.

return
true for this task.
since
Ant 1.7

        return getClass().equals(Tar.class);
    
protected voidtar(org.apache.tools.ant.types.ResourceCollection rc, org.apache.tools.tar.TarOutputStream tOut)
Adds the resources contained in this collection to the archive.

Uses the file based methods for file resources for backwards compatibility.

param
rc the collection containing resources to add
param
tOut stream writing to the archive.
throws
IOException on error.
since
Ant 1.7

        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.");
        }
        TarFileSet tfs = asTarFileSet(afs);

        if (isFileFileSet(rc)) {
            FileSet fs = (FileSet) rc;
            String[] files = getFileNames(fs);
            for (int i = 0; i < files.length; i++) {
                File f = new File(fs.getDir(getProject()), files[i]);
                String name = files[i].replace(File.separatorChar, '/");
                tarFile(f, tOut, name, tfs);
            }
        } else if (rc.isFilesystemOnly()) {
            Iterator iter = rc.iterator();
            while (iter.hasNext()) {
                FileResource r = (FileResource) iter.next();
                File f = r.getFile();
                if (f == null) {
                    f = new File(r.getBaseDir(), r.getName());
                }
                tarFile(f, tOut, f.getName(), tfs);
            }
        } else { // non-file resources
            Iterator iter = rc.iterator();
            while (iter.hasNext()) {
                Resource r = (Resource) iter.next();
                tarResource(r, tOut, r.getName(), tfs);
            }
        }
    
protected voidtarFile(java.io.File file, org.apache.tools.tar.TarOutputStream tOut, java.lang.String vPath, org.apache.tools.ant.taskdefs.Tar$TarFileSet tarFileSet)
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

        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);
    
protected voidtarResource(org.apache.tools.ant.types.Resource r, org.apache.tools.tar.TarOutputStream tOut, java.lang.String vPath, org.apache.tools.ant.taskdefs.Tar$TarFileSet 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


        if (!r.isExists()) {
            return;
        }

        if (tarFileSet != null) {
            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;
            }

            if (vPath.startsWith("/")
                && !tarFileSet.getPreserveLeadingSlashes()) {
                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());
            }
        }

        TarEntry te = new TarEntry(vPath);
        te.setModTime(r.getLastModified());
        // preserve permissions
        if (r instanceof ArchiveResource) {
            ArchiveResource ar = (ArchiveResource) r;
            te.setMode(ar.getMode());
            if (r instanceof TarResource) {
                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();

                byte[] buffer = new byte[8 * 1024];
                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);
        }