KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Tar


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs;
20
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Vector JavaDoc;
32 import java.util.zip.GZIPOutputStream JavaDoc;
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.DirectoryScanner;
35 import org.apache.tools.ant.Project;
36 import org.apache.tools.ant.types.ArchiveFileSet;
37 import org.apache.tools.ant.types.EnumeratedAttribute;
38 import org.apache.tools.ant.types.FileSet;
39 import org.apache.tools.ant.types.Resource;
40 import org.apache.tools.ant.types.ResourceCollection;
41 import org.apache.tools.ant.types.resources.ArchiveResource;
42 import org.apache.tools.ant.types.resources.FileResource;
43 import org.apache.tools.ant.types.selectors.SelectorUtils;
44 import org.apache.tools.ant.types.resources.TarResource;
45 import org.apache.tools.ant.util.FileUtils;
46 import org.apache.tools.ant.util.MergingMapper;
47 import org.apache.tools.ant.util.SourceFileScanner;
48 import org.apache.tools.bzip2.CBZip2OutputStream;
49 import org.apache.tools.tar.TarConstants;
50 import org.apache.tools.tar.TarEntry;
51 import org.apache.tools.tar.TarOutputStream;
52
53 /**
54  * Creates a tar archive.
55  *
56  * @since Ant 1.1
57  *
58  * @ant.task category="packaging"
59  */

60 public class Tar extends MatchingTask {
61
62     /**
63      * @deprecated since 1.5.x.
64      * Tar.WARN is deprecated and is replaced with
65      * Tar.TarLongFileMode.WARN
66      */

67     public static final String JavaDoc WARN = "warn";
68     /**
69      * @deprecated since 1.5.x.
70      * Tar.FAIL is deprecated and is replaced with
71      * Tar.TarLongFileMode.FAIL
72      */

73     public static final String JavaDoc FAIL = "fail";
74     /**
75      * @deprecated since 1.5.x.
76      * Tar.TRUNCATE is deprecated and is replaced with
77      * Tar.TarLongFileMode.TRUNCATE
78      */

79     public static final String JavaDoc TRUNCATE = "truncate";
80     /**
81      * @deprecated since 1.5.x.
82      * Tar.GNU is deprecated and is replaced with
83      * Tar.TarLongFileMode.GNU
84      */

85     public static final String JavaDoc GNU = "gnu";
86     /**
87      * @deprecated since 1.5.x.
88      * Tar.OMIT is deprecated and is replaced with
89      * Tar.TarLongFileMode.OMIT
90      */

91     public static final String JavaDoc OMIT = "omit";
92
93     // CheckStyle:VisibilityModifier OFF - bc
94
File JavaDoc tarFile;
95     File JavaDoc baseDir;
96
97     private TarLongFileMode longFileMode = new TarLongFileMode();
98
99     // need to keep the package private version for backwards compatibility
100
Vector JavaDoc filesets = new Vector JavaDoc();
101     // we must keep two lists since other classes may modify the
102
// filesets Vector (it is package private) without us noticing
103
private Vector JavaDoc resourceCollections = new Vector JavaDoc();
104
105     Vector JavaDoc fileSetFiles = new Vector JavaDoc();
106
107     // CheckStyle:VisibilityModifier ON
108

109     /**
110      * Indicates whether the user has been warned about long files already.
111      */

112     private boolean longWarningGiven = false;
113
114     private TarCompressionMethod compression = new TarCompressionMethod();
115
116     /**
117      * Add a new fileset with the option to specify permissions
118      * @return the tar fileset to be used as the nested element.
119      */

120     public TarFileSet createTarFileSet() {
121         TarFileSet fs = new TarFileSet();
122         fs.setProject(getProject());
123         filesets.addElement(fs);
124         return fs;
125     }
126
127     /**
128      * Add a collection of resources to archive.
129      * @param res a resource collection to archive.
130      * @since Ant 1.7
131      */

132     public void add(ResourceCollection res) {
133         resourceCollections.add(res);
134     }
135
136     /**
137      * Set is the name/location of where to create the tar file.
138      * @param tarFile the location of the tar file.
139      * @deprecated since 1.5.x.
140      * For consistency with other tasks, please use setDestFile().
141      */

142     public void setTarfile(File JavaDoc tarFile) {
143         this.tarFile = tarFile;
144     }
145
146     /**
147      * Set is the name/location of where to create the tar file.
148      * @since Ant 1.5
149      * @param destFile The output of the tar
150      */

151     public void setDestFile(File JavaDoc destFile) {
152         this.tarFile = destFile;
153     }
154
155     /**
156      * This is the base directory to look in for things to tar.
157      * @param baseDir the base directory.
158      */

159     public void setBasedir(File JavaDoc baseDir) {
160         this.baseDir = baseDir;
161     }
162
163     /**
164      * Set how to handle long files, those with a path>100 chars.
165      * Optional, default=warn.
166      * <p>
167      * Allowable values are
168      * <ul>
169      * <li> truncate - paths are truncated to the maximum length
170      * <li> fail - paths greater than the maximum cause a build exception
171      * <li> warn - paths greater than the maximum cause a warning and GNU is used
172      * <li> gnu - GNU extensions are used for any paths greater than the maximum.
173      * <li> omit - paths greater than the maximum are omitted from the archive
174      * </ul>
175      * @param mode the mode string to handle long files.
176      * @deprecated since 1.5.x.
177      * setLongFile(String) is deprecated and is replaced with
178      * setLongFile(Tar.TarLongFileMode) to make Ant's Introspection
179      * mechanism do the work and also to encapsulate operations on
180      * the mode in its own class.
181      */

182     public void setLongfile(String JavaDoc mode) {
183         log("DEPRECATED - The setLongfile(String) method has been deprecated."
184             + " Use setLongfile(Tar.TarLongFileMode) instead.");
185         this.longFileMode = new TarLongFileMode();
186         longFileMode.setValue(mode);
187     }
188
189     /**
190      * Set how to handle long files, those with a path&gt;100 chars.
191      * Optional, default=warn.
192      * <p>
193      * Allowable values are
194      * <ul>
195      * <li> truncate - paths are truncated to the maximum length
196      * <li> fail - paths greater than the maximum cause a build exception
197      * <li> warn - paths greater than the maximum cause a warning and GNU is used
198      * <li> gnu - GNU extensions are used for any paths greater than the maximum.
199      * <li> omit - paths greater than the maximum are omitted from the archive
200      * </ul>
201      * @param mode the mode to handle long file names.
202      */

203     public void setLongfile(TarLongFileMode mode) {
204         this.longFileMode = mode;
205     }
206
207     /**
208      * Set compression method.
209      * Allowable values are
210      * <ul>
211      * <li> none - no compression
212      * <li> gzip - Gzip compression
213      * <li> bzip2 - Bzip2 compression
214      * </ul>
215      * @param mode the compression method.
216      */

217     public void setCompression(TarCompressionMethod mode) {
218         this.compression = mode;
219     }
220
221     /**
222      * do the business
223      * @throws BuildException on error
224      */

225     public void execute() throws BuildException {
226         if (tarFile == null) {
227             throw new BuildException("tarfile attribute must be set!",
228                                      getLocation());
229         }
230
231         if (tarFile.exists() && tarFile.isDirectory()) {
232             throw new BuildException("tarfile is a directory!",
233                                      getLocation());
234         }
235
236         if (tarFile.exists() && !tarFile.canWrite()) {
237             throw new BuildException("Can not write to the specified tarfile!",
238                                      getLocation());
239         }
240
241         Vector JavaDoc savedFileSets = (Vector JavaDoc) filesets.clone();
242         try {
243             if (baseDir != null) {
244                 if (!baseDir.exists()) {
245                     throw new BuildException("basedir does not exist!",
246                                              getLocation());
247                 }
248
249                 // add the main fileset to the list of filesets to process.
250
TarFileSet mainFileSet = new TarFileSet(fileset);
251                 mainFileSet.setDir(baseDir);
252                 filesets.addElement(mainFileSet);
253             }
254
255             if (filesets.size() == 0 && resourceCollections.size() == 0) {
256                 throw new BuildException("You must supply either a basedir "
257                                          + "attribute or some nested resource"
258                                          + " collections.",
259                                          getLocation());
260             }
261
262             // check if tar is out of date with respect to each
263
// fileset
264
boolean upToDate = true;
265             for (Enumeration JavaDoc e = filesets.elements(); e.hasMoreElements();) {
266                 upToDate &= check((TarFileSet) e.nextElement());
267             }
268             for (Enumeration JavaDoc e = resourceCollections.elements();
269                  e.hasMoreElements();) {
270                 upToDate &= check((ResourceCollection) e.nextElement());
271             }
272
273             if (upToDate) {
274                 log("Nothing to do: " + tarFile.getAbsolutePath()
275                     + " is up to date.", Project.MSG_INFO);
276                 return;
277             }
278
279             log("Building tar: " + tarFile.getAbsolutePath(), Project.MSG_INFO);
280
281             TarOutputStream tOut = null;
282             try {
283                 tOut = new TarOutputStream(
284                     compression.compress(
285                         new BufferedOutputStream JavaDoc(
286                             new FileOutputStream JavaDoc(tarFile))));
287                 tOut.setDebug(true);
288                 if (longFileMode.isTruncateMode()) {
289                     tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE);
290                 } else if (longFileMode.isFailMode()
291                             || longFileMode.isOmitMode()) {
292                     tOut.setLongFileMode(TarOutputStream.LONGFILE_ERROR);
293                 } else {
294                     // warn or GNU
295
tOut.setLongFileMode(TarOutputStream.LONGFILE_GNU);
296                 }
297
298                 longWarningGiven = false;
299                 for (Enumeration JavaDoc e = filesets.elements();
300                      e.hasMoreElements();) {
301                     tar((TarFileSet) e.nextElement(), tOut);
302                 }
303                 for (Enumeration JavaDoc e = resourceCollections.elements();
304                      e.hasMoreElements();) {
305                     tar((ResourceCollection) e.nextElement(), tOut);
306                 }
307             } catch (IOException JavaDoc ioe) {
308                 String JavaDoc msg = "Problem creating TAR: " + ioe.getMessage();
309                 throw new BuildException(msg, ioe, getLocation());
310             } finally {
311                 FileUtils.close(tOut);
312             }
313         } finally {
314             filesets = savedFileSets;
315         }
316     }
317
318     /**
319      * tar a file
320      * @param file the file to tar
321      * @param tOut the output stream
322      * @param vPath the path name of the file to tar
323      * @param tarFileSet the fileset that the file came from.
324      * @throws IOException on error
325      */

326     protected void tarFile(File JavaDoc file, TarOutputStream tOut, String JavaDoc vPath,
327                            TarFileSet tarFileSet)
328         throws IOException JavaDoc {
329         if (file.equals(tarFile)) {
330             // If the archive is built for the first time and it is
331
// matched by a resource collection, then it hasn't been
332
// found in check (it hasn't been there) but will be
333
// included now.
334
//
335
// for some strange reason the old code would simply skip
336
// the entry and not fail, do the same now for backwards
337
// compatibility reasons. Without this, the which4j build
338
// fails in Gump
339
return;
340         }
341         tarResource(new FileResource(file), tOut, vPath, tarFileSet);
342     }
343
344     /**
345      * tar a resource
346      * @param r the resource to tar
347      * @param tOut the output stream
348      * @param vPath the path name of the file to tar
349      * @param tarFileSet the fileset that the file came from, may be null.
350      * @throws IOException on error
351      * @since Ant 1.7
352      */

353     protected void tarResource(Resource r, TarOutputStream tOut, String JavaDoc vPath,
354                                TarFileSet tarFileSet)
355         throws IOException JavaDoc {
356
357         if (!r.isExists()) {
358             return;
359         }
360
361         if (tarFileSet != null) {
362             String JavaDoc fullpath = tarFileSet.getFullpath(this.getProject());
363             if (fullpath.length() > 0) {
364                 vPath = fullpath;
365             } else {
366                 // don't add "" to the archive
367
if (vPath.length() <= 0) {
368                     return;
369                 }
370
371                 String JavaDoc prefix = tarFileSet.getPrefix(this.getProject());
372                 // '/' is appended for compatibility with the zip task.
373
if (prefix.length() > 0 && !prefix.endsWith("/")) {
374                     prefix = prefix + "/";
375                 }
376                 vPath = prefix + vPath;
377             }
378
379             if (vPath.startsWith("/")
380                 && !tarFileSet.getPreserveLeadingSlashes()) {
381                 int l = vPath.length();
382                 if (l <= 1) {
383                     // we would end up adding "" to the archive
384
return;
385                 }
386                 vPath = vPath.substring(1, l);
387             }
388         }
389
390         if (r.isDirectory() && !vPath.endsWith("/")) {
391             vPath += "/";
392         }
393
394         if (vPath.length() >= TarConstants.NAMELEN) {
395             if (longFileMode.isOmitMode()) {
396                 log("Omitting: " + vPath, Project.MSG_INFO);
397                 return;
398             } else if (longFileMode.isWarnMode()) {
399                 log("Entry: " + vPath + " longer than "
400                     + TarConstants.NAMELEN + " characters.",
401                     Project.MSG_WARN);
402                 if (!longWarningGiven) {
403                     log("Resulting tar file can only be processed "
404                         + "successfully by GNU compatible tar commands",
405                         Project.MSG_WARN);
406                     longWarningGiven = true;
407                 }
408             } else if (longFileMode.isFailMode()) {
409                 throw new BuildException("Entry: " + vPath
410                         + " longer than " + TarConstants.NAMELEN
411                         + "characters.", getLocation());
412             }
413         }
414
415         TarEntry te = new TarEntry(vPath);
416         te.setModTime(r.getLastModified());
417         // preserve permissions
418
if (r instanceof ArchiveResource) {
419             ArchiveResource ar = (ArchiveResource) r;
420             te.setMode(ar.getMode());
421             if (r instanceof TarResource) {
422                 TarResource tr = (TarResource) r;
423                 te.setUserName(tr.getUserName());
424                 te.setUserId(tr.getUid());
425                 te.setGroupName(tr.getGroup());
426                 te.setGroupId(tr.getGid());
427             }
428         }
429
430         if (!r.isDirectory()) {
431             if (r.size() > TarConstants.MAXSIZE) {
432                 throw new BuildException(
433                     "Resource: " + r + " larger than "
434                     + TarConstants.MAXSIZE + " bytes.");
435             }
436             te.setSize(r.getSize());
437             // override permissions if set explicitly
438
if (tarFileSet != null && tarFileSet.hasFileModeBeenSet()) {
439                 te.setMode(tarFileSet.getMode());
440             }
441         } else if (tarFileSet != null && tarFileSet.hasDirModeBeenSet()) {
442             // override permissions if set explicitly
443
te.setMode(tarFileSet.getDirMode(this.getProject()));
444         }
445
446         if (tarFileSet != null) {
447             // only override permissions if set explicitly
448
if (tarFileSet.hasUserNameBeenSet()) {
449                 te.setUserName(tarFileSet.getUserName());
450             }
451             if (tarFileSet.hasGroupBeenSet()) {
452                 te.setGroupName(tarFileSet.getGroup());
453             }
454             if (tarFileSet.hasUserIdBeenSet()) {
455                 te.setUserId(tarFileSet.getUid());
456             }
457             if (tarFileSet.hasGroupIdBeenSet()) {
458                 te.setGroupId(tarFileSet.getGid());
459             }
460         }
461
462         InputStream JavaDoc in = null;
463         try {
464             tOut.putNextEntry(te);
465
466             if (!r.isDirectory()) {
467                 in = r.getInputStream();
468
469                 byte[] buffer = new byte[8 * 1024];
470                 int count = 0;
471                 do {
472                     tOut.write(buffer, 0, count);
473                     count = in.read(buffer, 0, buffer.length);
474                 } while (count != -1);
475             }
476
477             tOut.closeEntry();
478         } finally {
479             FileUtils.close(in);
480         }
481     }
482
483     /**
484      * Is the archive up to date in relationship to a list of files.
485      * @param files the files to check
486      * @return true if the archive is up to date.
487      * @deprecated since 1.5.x.
488      * use the two-arg version instead.
489      */

490     protected boolean archiveIsUpToDate(String JavaDoc[] files) {
491         return archiveIsUpToDate(files, baseDir);
492     }
493
494     /**
495      * Is the archive up to date in relationship to a list of files.
496      * @param files the files to check
497      * @param dir the base directory for the files.
498      * @return true if the archive is up to date.
499      * @since Ant 1.5.2
500      */

501     protected boolean archiveIsUpToDate(String JavaDoc[] files, File JavaDoc dir) {
502         SourceFileScanner sfs = new SourceFileScanner(this);
503         MergingMapper mm = new MergingMapper();
504         mm.setTo(tarFile.getAbsolutePath());
505         return sfs.restrict(files, dir, null, mm).length == 0;
506     }
507
508     /**
509      * Is the archive up to date in relationship to a list of files.
510      * @param r the files to check
511      * @return true if the archive is up to date.
512      * @since Ant 1.7
513      */

514     protected boolean archiveIsUpToDate(Resource r) {
515         return SelectorUtils.isOutOfDate(new FileResource(tarFile), r,
516                                          FileUtils.getFileUtils()
517                                          .getFileTimestampGranularity());
518     }
519
520     /**
521      * Whether this task can deal with non-file resources.
522      *
523      * <p>This implementation returns true only if this task is
524      * &lt;tar&gt;. Any subclass of this class that also wants to
525      * support non-file resources needs to override this method. We
526      * need to do so for backwards compatibility reasons since we
527      * can't expect subclasses to support resources.</p>
528      * @return true for this task.
529      * @since Ant 1.7
530      */

531     protected boolean supportsNonFileResources() {
532         return getClass().equals(Tar.class);
533     }
534
535     /**
536      * Checks whether the archive is out-of-date with respect to the resources
537      * of the given collection.
538      *
539      * <p>Also checks that either all collections only contain file
540      * resources or this class supports non-file collections.</p>
541      *
542      * <p>And - in case of file-collections - ensures that the archive won't
543      * contain itself.</p>
544      *
545      * @param rc the resource collection to check
546      * @return whether the archive is up-to-date
547      * @since Ant 1.7
548      */

549     protected boolean check(ResourceCollection rc) {
550         boolean upToDate = true;
551         if (isFileFileSet(rc)) {
552             FileSet fs = (FileSet) rc;
553             upToDate = check(fs.getDir(getProject()), getFileNames(fs));
554         } else if (!rc.isFilesystemOnly() && !supportsNonFileResources()) {
555             throw new BuildException("only filesystem resources are supported");
556         } else if (rc.isFilesystemOnly()) {
557             HashSet JavaDoc basedirs = new HashSet JavaDoc();
558             HashMap JavaDoc basedirToFilesMap = new HashMap JavaDoc();
559             Iterator JavaDoc iter = rc.iterator();
560             while (iter.hasNext()) {
561                 FileResource r = (FileResource) iter.next();
562                 File JavaDoc base = r.getBaseDir();
563                 if (base == null) {
564                     base = Copy.NULL_FILE_PLACEHOLDER;
565                 }
566                 basedirs.add(base);
567                 Vector JavaDoc files = (Vector JavaDoc) basedirToFilesMap.get(base);
568                 if (files == null) {
569                     files = new Vector JavaDoc();
570                     basedirToFilesMap.put(base, new Vector JavaDoc());
571                 }
572                 files.add(r.getName());
573             }
574             iter = basedirs.iterator();
575             while (iter.hasNext()) {
576                 File JavaDoc base = (File JavaDoc) iter.next();
577                 Vector JavaDoc f = (Vector JavaDoc) basedirToFilesMap.get(base);
578                 String JavaDoc[] files = (String JavaDoc[]) f.toArray(new String JavaDoc[f.size()]);
579                 upToDate &=
580                     check(base == Copy.NULL_FILE_PLACEHOLDER ? null : base,
581                           files);
582             }
583         } else { // non-file resources
584
Iterator JavaDoc iter = rc.iterator();
585             while (upToDate && iter.hasNext()) {
586                 Resource r = (Resource) iter.next();
587                 upToDate &= archiveIsUpToDate(r);
588             }
589         }
590
591         return upToDate;
592     }
593
594     /**
595      * Checks whether the archive is out-of-date with respect to the
596      * given files, ensures that the archive won't contain itself.</p>
597      *
598      * @param basedir base directory for file names
599      * @param files array of relative file names
600      * @return whether the archive is up-to-date
601      * @since Ant 1.7
602      */

603     protected boolean check(File JavaDoc basedir, String JavaDoc[] files) {
604         boolean upToDate = true;
605         if (!archiveIsUpToDate(files, basedir)) {
606             upToDate = false;
607         }
608
609         for (int i = 0; i < files.length; ++i) {
610             if (tarFile.equals(new File JavaDoc(basedir, files[i]))) {
611                 throw new BuildException("A tar file cannot include "
612                                          + "itself", getLocation());
613             }
614         }
615         return upToDate;
616     }
617
618     /**
619      * Adds the resources contained in this collection to the archive.
620      *
621      * <p>Uses the file based methods for file resources for backwards
622      * compatibility.</p>
623      *
624      * @param rc the collection containing resources to add
625      * @param tOut stream writing to the archive.
626      * @throws IOException on error.
627      * @since Ant 1.7
628      */

629     protected void tar(ResourceCollection rc, TarOutputStream tOut)
630         throws IOException JavaDoc {
631         ArchiveFileSet afs = null;
632         if (rc instanceof ArchiveFileSet) {
633             afs = (ArchiveFileSet) rc;
634         }
635         if (afs != null && afs.size() > 1
636             && afs.getFullpath(this.getProject()).length() > 0) {
637             throw new BuildException("fullpath attribute may only "
638                                      + "be specified for "
639                                      + "filesets that specify a "
640                                      + "single file.");
641         }
642         TarFileSet tfs = asTarFileSet(afs);
643
644         if (isFileFileSet(rc)) {
645             FileSet fs = (FileSet) rc;
646             String JavaDoc[] files = getFileNames(fs);
647             for (int i = 0; i < files.length; i++) {
648                 File JavaDoc f = new File JavaDoc(fs.getDir(getProject()), files[i]);
649                 String JavaDoc name = files[i].replace(File.separatorChar, '/');
650                 tarFile(f, tOut, name, tfs);
651             }
652         } else if (rc.isFilesystemOnly()) {
653             Iterator JavaDoc iter = rc.iterator();
654             while (iter.hasNext()) {
655                 FileResource r = (FileResource) iter.next();
656                 File JavaDoc f = r.getFile();
657                 if (f == null) {
658                     f = new File JavaDoc(r.getBaseDir(), r.getName());
659                 }
660                 tarFile(f, tOut, f.getName(), tfs);
661             }
662         } else { // non-file resources
663
Iterator JavaDoc iter = rc.iterator();
664             while (iter.hasNext()) {
665                 Resource r = (Resource) iter.next();
666                 tarResource(r, tOut, r.getName(), tfs);
667             }
668         }
669     }
670
671     /**
672      * whether the given resource collection is a (subclass of)
673      * FileSet that only contains file system resources.
674      * @param rc the resource collection to check.
675      * @return true if the collection is a fileset.
676      * @since Ant 1.7
677      */

678     protected static final boolean isFileFileSet(ResourceCollection rc) {
679         return rc instanceof FileSet && rc.isFilesystemOnly();
680     }
681
682     /**
683      * Grabs all included files and directors from the FileSet and
684      * returns them as an array of (relative) file names.
685      * @param fs the fileset to operate on.
686      * @return a list of the filenames.
687      * @since Ant 1.7
688      */

689     protected static final String JavaDoc[] getFileNames(FileSet fs) {
690         DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject());
691         String JavaDoc[] directories = ds.getIncludedDirectories();
692         String JavaDoc[] filesPerSe = ds.getIncludedFiles();
693         String JavaDoc[] files = new String JavaDoc [directories.length + filesPerSe.length];
694         System.arraycopy(directories, 0, files, 0, directories.length);
695         System.arraycopy(filesPerSe, 0, files, directories.length,
696                          filesPerSe.length);
697         return files;
698     }
699
700     /**
701      * Copies fullpath, prefix and permission attributes from the
702      * ArchiveFileSet to a new TarFileSet (or returns it unchanged if
703      * it already is a TarFileSet).
704      *
705      * @param archiveFileSet fileset to copy attributes from, may be null
706      * @return a new TarFileSet.
707      * @since Ant 1.7
708      */

709     protected TarFileSet asTarFileSet(ArchiveFileSet archiveFileSet) {
710         TarFileSet tfs = null;
711         if (archiveFileSet != null && archiveFileSet instanceof TarFileSet) {
712             tfs = (TarFileSet) archiveFileSet;
713         } else {
714             tfs = new TarFileSet();
715             tfs.setProject(getProject());
716             if (archiveFileSet != null) {
717                 tfs.setPrefix(archiveFileSet.getPrefix(getProject()));
718                 tfs.setFullpath(archiveFileSet.getFullpath(getProject()));
719                 if (archiveFileSet.hasFileModeBeenSet()) {
720                     tfs.integerSetFileMode(archiveFileSet
721                                            .getFileMode(getProject()));
722                 }
723                 if (archiveFileSet.hasDirModeBeenSet()) {
724                     tfs.integerSetDirMode(archiveFileSet
725                                           .getDirMode(getProject()));
726                 }
727
728                 if (archiveFileSet
729                     instanceof org.apache.tools.ant.types.TarFileSet) {
730                     org.apache.tools.ant.types.TarFileSet t =
731                         (org.apache.tools.ant.types.TarFileSet) archiveFileSet;
732                     if (t.hasUserNameBeenSet()) {
733                         tfs.setUserName(t.getUserName());
734                     }
735                     if (t.hasGroupBeenSet()) {
736                         tfs.setGroup(t.getGroup());
737                     }
738                     if (t.hasUserIdBeenSet()) {
739                         tfs.setUid(t.getUid());
740                     }
741                     if (t.hasGroupIdBeenSet()) {
742                         tfs.setGid(t.getGid());
743                     }
744                 }
745             }
746         }
747         return tfs;
748     }
749
750     /**
751      * This is a FileSet with the option to specify permissions
752      * and other attributes.
753      */

754     public static class TarFileSet
755         extends org.apache.tools.ant.types.TarFileSet {
756         private String JavaDoc[] files = null;
757
758         private boolean preserveLeadingSlashes = false;
759
760         /**
761          * Creates a new <code>TarFileSet</code> instance.
762          * Using a fileset as a constructor argument.
763          *
764          * @param fileset a <code>FileSet</code> value
765          */

766         public TarFileSet(FileSet fileset) {
767             super(fileset);
768         }
769
770         /**
771          * Creates a new <code>TarFileSet</code> instance.
772          *
773          */

774         public TarFileSet() {
775             super();
776         }
777
778         /**
779          * Get a list of files and directories specified in the fileset.
780          * @param p the current project.
781          * @return a list of file and directory names, relative to
782          * the baseDir for the project.
783          */

784         public String JavaDoc[] getFiles(Project p) {
785             if (files == null) {
786                 files = getFileNames(this);
787             }
788
789             return files;
790         }
791
792         /**
793          * A 3 digit octal string, specify the user, group and
794          * other modes in the standard Unix fashion;
795          * optional, default=0644
796          * @param octalString a 3 digit octal string.
797          */

798         public void setMode(String JavaDoc octalString) {
799             setFileMode(octalString);
800         }
801
802         /**
803          * @return the current mode.
804          */

805         public int getMode() {
806             return getFileMode(this.getProject());
807         }
808
809         /**
810          * Flag to indicates whether leading `/'s should
811          * be preserved in the file names.
812          * Optional, default is <code>false</code>.
813          * @param b the leading slashes flag.
814          */

815         public void setPreserveLeadingSlashes(boolean b) {
816             this.preserveLeadingSlashes = b;
817         }
818
819         /**
820          * @return the leading slashes flag.
821          */

822         public boolean getPreserveLeadingSlashes() {
823             return preserveLeadingSlashes;
824         }
825     }
826
827     /**
828      * Set of options for long file handling in the task.
829      *
830      */

831     public static class TarLongFileMode extends EnumeratedAttribute {
832
833         /** permissible values for longfile attribute */
834         public static final String JavaDoc
835             WARN = "warn",
836             FAIL = "fail",
837             TRUNCATE = "truncate",
838             GNU = "gnu",
839             OMIT = "omit";
840
841         private final String JavaDoc[] validModes = {WARN, FAIL, TRUNCATE, GNU, OMIT};
842
843         /** Constructor, defaults to "warn" */
844         public TarLongFileMode() {
845             super();
846             setValue(WARN);
847         }
848
849         /**
850          * @return the possible values for this enumerated type.
851          */

852         public String JavaDoc[] getValues() {
853             return validModes;
854         }
855
856         /**
857          * @return true if value is "truncate".
858          */

859         public boolean isTruncateMode() {
860             return TRUNCATE.equalsIgnoreCase(getValue());
861         }
862
863         /**
864          * @return true if value is "warn".
865          */

866         public boolean isWarnMode() {
867             return WARN.equalsIgnoreCase(getValue());
868         }
869
870         /**
871          * @return true if value is "gnu".
872          */

873         public boolean isGnuMode() {
874             return GNU.equalsIgnoreCase(getValue());
875         }
876
877         /**
878          * @return true if value is "fail".
879          */

880         public boolean isFailMode() {
881             return FAIL.equalsIgnoreCase(getValue());
882         }
883
884         /**
885          * @return true if value is "omit".
886          */

887         public boolean isOmitMode() {
888             return OMIT.equalsIgnoreCase(getValue());
889         }
890     }
891
892     /**
893      * Valid Modes for Compression attribute to Tar Task
894      *
895      */

896     public static final class TarCompressionMethod extends EnumeratedAttribute {
897
898         // permissible values for compression attribute
899
/**
900          * No compression
901          */

902         private static final String JavaDoc NONE = "none";
903         /**
904          * GZIP compression
905          */

906         private static final String JavaDoc GZIP = "gzip";
907         /**
908          * BZIP2 compression
909          */

910         private static final String JavaDoc BZIP2 = "bzip2";
911
912
913         /**
914          * Default constructor
915          */

916         public TarCompressionMethod() {
917             super();
918             setValue(NONE);
919         }
920
921         /**
922          * Get valid enumeration values.
923          * @return valid enumeration values
924          */

925         public String JavaDoc[] getValues() {
926             return new String JavaDoc[] {NONE, GZIP, BZIP2 };
927         }
928
929         /**
930          * This method wraps the output stream with the
931          * corresponding compression method
932          *
933          * @param ostream output stream
934          * @return output stream with on-the-fly compression
935          * @exception IOException thrown if file is not writable
936          */

937         private OutputStream JavaDoc compress(final OutputStream JavaDoc ostream)
938             throws IOException JavaDoc {
939             final String JavaDoc v = getValue();
940             if (GZIP.equals(v)) {
941                 return new GZIPOutputStream JavaDoc(ostream);
942             } else {
943                 if (BZIP2.equals(v)) {
944                     ostream.write('B');
945                     ostream.write('Z');
946                     return new CBZip2OutputStream(ostream);
947                 }
948             }
949             return ostream;
950         }
951     }
952 }
953
Popular Tags