From 80d371a3b4e1ba3f845e1b9a8f831fd6a11fafd5 Mon Sep 17 00:00:00 2001 From: Magesh Umasankar Date: Wed, 21 Nov 2001 07:31:01 +0000 Subject: [PATCH] 1. Refactored Untar to extend from Expand, as untar is very similar to unjar, unwar and unzip. 2. Added 2 new attributes to these tasks - outfile and verbose 3. Nested Patternsets can be used to specify what files are to be extracted from within the archive. 4. Nested Filesets can be specified to select previously archived files for unarchival (PR: 3074) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269973 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/CoreTasks/untar.html | 43 +-- docs/manual/CoreTasks/unzip.html | 67 +++- docs/manual/coretasklist.html | 2 +- .../apache/tools/ant/DirectoryScanner.java | 2 +- .../org/apache/tools/ant/taskdefs/Expand.java | 340 ++++++++++++++---- .../org/apache/tools/ant/taskdefs/Untar.java | 205 +++++------ src/main/org/apache/tools/tar/TarEntry.java | 9 + 7 files changed, 442 insertions(+), 226 deletions(-) diff --git a/docs/manual/CoreTasks/untar.html b/docs/manual/CoreTasks/untar.html index cd678ebbb..2563280be 100644 --- a/docs/manual/CoreTasks/untar.html +++ b/docs/manual/CoreTasks/untar.html @@ -11,48 +11,7 @@

Description

Untars a tarfile.

-

Note: File permissions will not be restored on extracted files.

- -

For JDK 1.1 "last modified time" field is set to current time instead of being -carried from tarfile.

- -

The untar task recognizes the long pathname entries used by GNU tar.

- -

Parameters

- - - - - - - - - - - - - - - - - - - - - -
AttributeDescriptionRequired
srctarfile to expand.Yes
destdirectory where to store the expanded files.Yes
overwriteOverwrite files, even if they are newer than the - corresponding entries in the archive (true or false, default is - true).No
-

Examples

-
-

-<gunzip src="tools.tar.gz"/>
-<untar src="tools.tar" dest="${tools.home}"/> -

-
-
-

Copyright © 2000,2001 Apache Software Foundation. All rights -Reserved.

+This document has moved here diff --git a/docs/manual/CoreTasks/unzip.html b/docs/manual/CoreTasks/unzip.html index a7d0f39d5..77d564333 100644 --- a/docs/manual/CoreTasks/unzip.html +++ b/docs/manual/CoreTasks/unzip.html @@ -7,12 +7,19 @@ -

Unjar/Unwar/Unzip

+

Unjar/Untar/Unwar/Unzip

Description

-

Unzips a zip-, war- or jarfile.

-

For JDK 1.1 "last modified time" field is set to current time instead of being -carried from zipfile.

+

Unzips a zip-, war-, tar- or jarfile.

+

For JDK 1.1 "last modified time" field is set to current time instead of being +carried from the archive file.

+

PatternSets are used to select files to extract +from the archive. If no patternset is used, all files are extracted. +

+

FileSets may be used used to select archived files +to perform unarchival upon. +

File permissions will not be restored on extracted files.

+

The untar task recognizes the long pathname entries used by GNU tar.

Parameters

@@ -22,13 +29,13 @@ carried from zipfile.

- - + + - + @@ -37,12 +44,58 @@ carried from zipfile.

true). + + + + + + + + + +
srczipfile to expand.Yesarchive file to expand.Yes, if filesets are not used.
dest directory where to store the expanded files.YesYes, if outfile is not specified.
overwrite No
outfileList the contents of the archive into this file.Yes, if dest is not specified.
verboseInclude file details when listing contents of + the archive into outfile? Defaults to false.No

Examples

<unzip src="${tomcat_src}/tools-src.zip" dest="${tools.home}" />

+
+

+<gunzip src="tools.tar.gz"/>
+<untar src="tools.tar" dest="${tools.home}"/> +

+
+
+

+<unzip src="${tomcat_src}/tools-src.zip"
+       dest="${tools.home}"
+       outfile="${outfile}"
+       vebose="on">
+    <patternset>
+        <include name="**/*.java"/>
+        <exclude name="**/Test*.java"/>
+    <patternset/>
+<unzip/>
+

+
+
+

+<unzip dest="${tools.home}"
+       outfile="${outfile}"
+       vebose="on">
+    <patternset>
+        <include name="**/*.java"/>
+        <exclude name="**/Test*.java"/>
+    <patternset/>
+    <fileset dir=".">
+        <include name="**/*.zip"/>
+        <exclude name="**/tmp*.zip"/>
+    <fileset/>
+<unzip/>
+

+

Copyright © 2000,2001 Apache Software Foundation. All rights Reserved.

diff --git a/docs/manual/coretasklist.html b/docs/manual/coretasklist.html index dfe2a3117..31e4e5be2 100644 --- a/docs/manual/coretasklist.html +++ b/docs/manual/coretasklist.html @@ -77,7 +77,7 @@ TStamp
Typedef
Unjar
-Untar
+Untar
Unwar
Unzip
Uptodate
diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 0964079b9..0359dd603 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -468,7 +468,7 @@ strLoop: * @return true when the string matches against the pattern, * false otherwise. */ - protected static boolean match(String pattern, String str) { + public static boolean match(String pattern, String str) { return match(pattern, str, true); } diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java index 971a6c111..35fc3f61e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Expand.java +++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 1999 The Apache Software Foundation. All rights + * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -9,7 +9,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -17,15 +17,15 @@ * distribution. * * 3. The end-user documentation included with the redistribution, if - * any, must include the following acknowlegement: - * "This product includes software developed by the + * any, must include the following acknowlegement: + * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived - * from this software without prior written permission. For written + * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" @@ -57,25 +57,41 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.PatternSet; +import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.InputStream; import java.io.IOException; +import java.io.PrintWriter; +import java.util.Date; +import java.util.Vector; import java.util.zip.ZipInputStream; import java.util.zip.ZipEntry; + /** - * Unzip a file. + * Unzip a file. * * @author costin@dnt.ro * @author Stefan Bodewig + * @author Magesh Umasankar */ public class Expand extends MatchingTask { - private File dest; // req - private File source; // req + protected File dest; + protected File source; // req + protected File outFile; + protected boolean overwrite = true; + protected boolean verbose; + protected PrintWriter pw = null; + protected BufferedWriter bw = null; + protected FileWriter fw = null; + protected Vector patternsets = new Vector(); + protected Vector filesets = new Vector(); - private boolean overwrite = true; - /** * Do the work. * @@ -86,84 +102,118 @@ public class Expand extends MatchingTask { if ("expand".equals(taskType)) { log("!! expand is deprecated. Use unzip instead. !!"); } - + + if (source == null && filesets.size() == 0) { + throw new BuildException("src attribute and/or filesets must be specified"); + } + + if (dest == null && outFile == null) { + throw new BuildException( + "Dest and/or the OutFile attribute " + + "must be specified"); + } + + if (dest != null && dest.exists() && !dest.isDirectory()) { + throw new BuildException("Dest must be a directory.", location); + } + + if (verbose && outFile == null) { + throw new BuildException( + "Verbose can be set only when OutFile is " + + "specified"); + } Touch touch = (Touch) project.createTask("touch"); touch.setOwningTarget(target); touch.setTaskName(getTaskName()); touch.setLocation(getLocation()); - - if (source == null) { - throw new BuildException("Source attribute must be specified"); + + try { + if (outFile != null) { + if (outFile.isDirectory()) { + throw new BuildException("Outfile " + outFile + + " must not be a directory."); + } + if (!outFile.exists()) { + File parent = new File(outFile.getParent()); + if (!parent.exists()) { + if (!parent.mkdirs()) { + throw new BuildException("Unable to create " + + outFile); + } + } + } + fw = new FileWriter(outFile); + bw = new BufferedWriter(fw); + pw = new PrintWriter(bw, true); + } + } catch (IOException ioe) { + throw new BuildException(ioe.getMessage(), location); } - if (dest == null) { - throw new BuildException("Dest attribute must be specified"); + if (source != null) { + if (source.isDirectory()) { + // get all the files in the descriptor directory + DirectoryScanner ds = super.getDirectoryScanner(source); + + String[] files = ds.getIncludedFiles(); + for (int i = 0; i < files.length; ++i) { + File file = new File(source, files[i]); + expandFile(touch, file, dest); + } + } + else { + expandFile(touch, source, dest); + } } + if (filesets.size() > 0) { + for (int j=0; j < filesets.size(); j++) { + FileSet fs = (FileSet) filesets.elementAt(j); + DirectoryScanner ds = fs.getDirectoryScanner(project); + File fromDir = fs.getDir(project); - if (source.isDirectory()) { - // get all the files in the descriptor directory - DirectoryScanner ds = super.getDirectoryScanner(source); - - String[] files = ds.getIncludedFiles(); - for (int i = 0; i < files.length; ++i) { - File file = new File(source, files[i]); - expandFile(touch, file, dest); + String[] files = ds.getIncludedFiles(); + for (int i = 0; i < files.length; ++i) { + File file = new File(fromDir, files[i]); + expandFile(touch, file, dest); + } } } - else { - expandFile(touch, source, dest); + try { + if (pw != null) { + pw.close(); + } + if (bw != null) { + bw.close(); + } + if (fw != null) { + fw.close(); + } + } catch (IOException ioe1) { + //Oh, well! We did our best } } - private void expandFile(Touch touch, File srcF, File dir) { + /* + * This method is to be overridden by extending unarchival tasks. + */ + protected void expandFile(Touch touch, File srcF, File dir) { ZipInputStream zis = null; try { - log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); // code from WarExpand zis = new ZipInputStream(new FileInputStream(srcF)); ZipEntry ze = null; while ((ze = zis.getNextEntry()) != null) { - File f = new File(dir, project.translatePath(ze.getName())); - try { - if (!overwrite && f.exists() - && f.lastModified() >= ze.getTime()) { - log("Skipping " + f + " as it is up-to-date", - Project.MSG_DEBUG); - continue; - } - - log("expanding " + ze.getName() + " to "+ f, - Project.MSG_VERBOSE); - // create intermediary directories - sometimes zip don't add them - File dirF=new File(f.getParent()); - dirF.mkdirs(); - - if (ze.isDirectory()) { - f.mkdirs(); - } else { - byte[] buffer = new byte[1024]; - int length = 0; - FileOutputStream fos = new FileOutputStream(f); - - while ((length = zis.read(buffer)) >= 0) { - fos.write(buffer, 0, length); - } - - fos.close(); - } - - if (project.getJavaVersion() != Project.JAVA_1_1) { - touch.setFile(f); - touch.setMillis(ze.getTime()); - touch.touch(); - } - - } catch( FileNotFoundException ex ) { - log("Unable to expand to file " + f.getPath(), Project.MSG_WARN); - } + extractFile(touch, srcF, dir, zis, + ze.getName(), ze.getSize(), + new Date(ze.getTime()), + ze.isDirectory()); } - log("expand complete", Project.MSG_VERBOSE ); + + if (dest != null) { + log("expand complete", Project.MSG_VERBOSE ); + } + } catch (IOException ioe) { throw new BuildException("Error while expanding " + srcF.getPath(), ioe); } finally { @@ -175,7 +225,131 @@ public class Expand extends MatchingTask { } } } - + + protected void extractFile(Touch touch, File srcF, File dir, + InputStream compressedInputStream, + String entryName, long entrySize, + Date entryDate, boolean isDirectory) + throws IOException { + extractFile(touch, srcF, dir, compressedInputStream, + entryName, entrySize, entryDate, isDirectory, + null, null); + + } + + protected void extractFile(Touch touch, File srcF, File dir, + InputStream compressedInputStream, + String entryName, long entrySize, + Date entryDate, boolean isDirectory, + String modeStr, String userGroup) + throws IOException { + + if (patternsets != null && patternsets.size() > 0) { + String name = entryName; + boolean included = false; + for (int v = 0; v < patternsets.size(); v++) { + PatternSet p = (PatternSet) patternsets.elementAt(v); + String[] incls = p.getIncludePatterns(project); + if (incls != null) { + for (int w = 0; w < incls.length; w++) { + boolean isIncl = DirectoryScanner.match(incls[w], name); + if (isIncl) { + included = true; + break; + } + } + } + String[] excls = p.getExcludePatterns(project); + if (excls != null) { + for (int w = 0; w < excls.length; w++) { + boolean isExcl = DirectoryScanner.match(excls[w], name); + if (isExcl) { + included = false; + break; + } + } + } + } + if (!included) { + //Do not process this file + return; + } + } + + if (dest != null) { + log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); + } + + if (outFile != null) { + if (verbose) { + StringBuffer sb = new StringBuffer(); + if (modeStr != null) { + sb.append(modeStr); + sb.append(' '); + } + if (userGroup != null) { + sb.append(userGroup); + sb.append(' '); + } + String s = Long.toString(entrySize); + int len = s.length(); + for(int i = 6 - len; i > 0; i--) { + sb.append(' '); + } + sb.append(s) + .append(' ') + .append(entryDate.toString()); + sb.append(' ') + .append(entryName); + pw.println(sb); + } else { + pw.println(entryName); + } + } + if (dest != null) { + File f = new File(dir, project.translatePath(entryName)); + try { + if (!overwrite && f.exists() + && f.lastModified() >= entryDate.getTime()) { + log("Skipping " + f + " as it is up-to-date", + Project.MSG_DEBUG); + return; + } + + log("expanding " + entryName + " to "+ f, + Project.MSG_VERBOSE); + // create intermediary directories - sometimes zip don't add them + File dirF=new File(f.getParent()); + dirF.mkdirs(); + + if (isDirectory) { + f.mkdirs(); + } else { + byte[] buffer = new byte[1024]; + int length = 0; + FileOutputStream fos = new FileOutputStream(f); + + while ((length = + compressedInputStream.read(buffer)) >= 0) { + fos.write(buffer, 0, length); + } + + fos.close(); + } + + if (project.getJavaVersion() != Project.JAVA_1_1) { + touch.setFile(f); + touch.setMillis(entryDate.getTime()); + touch.touch(); + } + + } catch( FileNotFoundException ex ) { + log("Unable to expand to file " + f.getPath(), Project.MSG_WARN); + } + } + + } + /** * Set the destination directory. File will be unzipped into the * destination directory. @@ -203,4 +377,34 @@ public class Expand extends MatchingTask { overwrite = b; } + /** + * Set the output file to be used to store the list of the + * archive's contents. + * + * @param outFile the output file to be used. + */ + public void setOutfile(File outFile) { + this.outFile = outFile; + } + + /** + * Set the verbose mode for the contents-list file. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * Add a patternset + */ + public void addPatternset(PatternSet set) { + patternsets.addElement(set); + } + + /** + * Add a fileset + */ + public void addFileset(FileSet set) { + filesets.addElement(set); + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/Untar.java b/src/main/org/apache/tools/ant/taskdefs/Untar.java index 5bce2775a..cf0cf8fbb 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Untar.java +++ b/src/main/org/apache/tools/ant/taskdefs/Untar.java @@ -54,16 +54,15 @@ package org.apache.tools.ant.taskdefs; -import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Expand; import org.apache.tools.tar.TarInputStream; import org.apache.tools.tar.TarEntry; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Date; /** * Untar a file. @@ -71,124 +70,116 @@ import java.io.IOException; * Heavily based on the Expand task. * * @author Stefan Bodewig + * @author Magesh Umasankar */ -public class Untar extends Task { - private File dest; // req - private File source; // req - - private boolean overwrite = true; - - /** - * Do the work. - * - * @exception BuildException Thrown in unrecoverable error. - */ - public void execute() throws BuildException { - - Touch touch = (Touch) project.createTask("touch"); - touch.setOwningTarget(target); - touch.setTaskName(getTaskName()); - touch.setLocation(getLocation()); - - File srcF = source; - +public class Untar extends Expand { + private final static int S_IFMT = 0170000; + private final static int S_IFSOCK = 0140000; + private final static int S_IFLNK = 0120000; + private final static int S_IFREG = 0100000; + private final static int S_IFBLK = 0060000; + private final static int S_IFDIR = 0040000; + private final static int S_IFCHR = 0020000; + private final static int S_IFIFO = 0010000; + private final static int S_ISUID = 0004000; + private final static int S_ISGID = 0002000; + private final static int S_ISVTX = 0001000; + private final static int S_IRWXU = 00700; + private final static int S_IRUSR = 00400; + private final static int S_IWUSR = 00200; + private final static int S_IXUSR = 00100; + private final static int S_IRWXG = 00070; + private final static int S_IRGRP = 00040; + private final static int S_IWGRP = 00020; + private final static int S_IXGRP = 00010; + private final static int S_IRWXO = 00007; + private final static int S_IROTH = 00004; + private final static int S_IWOTH = 00002; + private final static int S_IXOTH = 00001; + + protected void expandFile(Touch touch, File srcF, File dir) { TarInputStream tis = null; try { - if (source == null) { - throw new BuildException("No source specified", location); - } - if (!srcF.exists()) { - throw new BuildException("source "+srcF+" doesn't exist", - location); - } - - if (dest == null) { - throw new BuildException("No destination specified", location); + if (dest != null) { + log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); } - File dir = dest; - log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); tis = new TarInputStream(new FileInputStream(srcF)); TarEntry te = null; while ((te = tis.getNextEntry()) != null) { - try { - File f = new File(dir, project.translatePath(te.getName())); - if (!overwrite && f.exists() - && f.lastModified() >= te.getModTime().getTime()) { - log("Skipping " + f + " as it is up-to-date", - Project.MSG_DEBUG); - continue; - } - - log("expanding " + te.getName() + " to "+ f, - Project.MSG_VERBOSE); - File dirF=new File(f.getParent()); - dirF.mkdirs(); - - if (te.isDirectory()) { - f.mkdirs(); - } else { - byte[] buffer = new byte[1024]; - int length = 0; - FileOutputStream fos = new FileOutputStream(f); - - while ((length = tis.read(buffer)) >= 0) { - fos.write(buffer, 0, length); - } - - fos.close(); - } - - if (project.getJavaVersion() != Project.JAVA_1_1) { - touch.setFile(f); - touch.setMillis(te.getModTime().getTime()); - touch.touch(); - } - - } catch(FileNotFoundException ex) { - log("FileNotFoundException: " + te.getName(), - Project.MSG_WARN); - } + extractFile(touch, srcF, dir, tis, + te.getName(), te.getSize(), + te.getModTime(), te.isDirectory(), + mode2str(te.getMode()), + te.getUserId() + "/" + te.getGroupId()); + } + if (dest != null) { + log("expand complete", Project.MSG_VERBOSE ); } + } catch (IOException ioe) { throw new BuildException("Error while expanding " + srcF.getPath(), ioe, location); - } finally { - if (tis != null) { - try { - tis.close(); - } - catch (IOException e) {} - } - } - } - - /** - * Set the destination directory. File will be untared into the - * destination directory. - * - * @param d Path to the directory. - */ - public void setDest(File d) { - this.dest = d; - } - - /** - * Set the path to tar-file. - * - * @param s Path to tar-file. - */ - public void setSrc(File s) { - this.source = s; + } finally { + if (tis != null) { + try { + tis.close(); + } + catch (IOException e) {} + } + } } - /** - * Should we overwrite files in dest, even if they are newer than - * the corresponding entries in the archive? - */ - public void setOverwrite(boolean b) { - overwrite = b; + private String mode2str(int mode) { + StringBuffer sb = new StringBuffer("----------"); + if ((mode & S_IFREG ) == 0) { + if ((mode & S_IFDIR ) != 0) { + sb.setCharAt(0, 'd'); + } else if ((mode & S_IFLNK) != 0) { + sb.setCharAt(0, 'l'); + } else if ((mode & S_IFIFO) != 0) { + sb.setCharAt(0, 'p'); + } else if ((mode & S_IFCHR) != 0) { + sb.setCharAt(0, 'c'); + } else if ((mode & S_IFBLK) != 0) { + sb.setCharAt(0, 'b'); + } else if ((mode & S_IFSOCK) != 0) { + sb.setCharAt(0, 's'); + } else if ((mode & S_IFIFO) != 0) { + sb.setCharAt(0, 'p'); + } + } + + if ((mode & S_IRUSR ) != 0) { + sb.setCharAt(1, 'r'); + } + if ((mode & S_IWUSR ) != 0) { + sb.setCharAt(2, 'w'); + } + if ((mode & S_IXUSR ) != 0) { + sb.setCharAt(3, 'x'); + } + + if ((mode & S_IRGRP ) != 0) { + sb.setCharAt(4, 'r'); + } + if ((mode & S_IWGRP ) != 0) { + sb.setCharAt(5, 'w'); + } + if ((mode & S_IXGRP ) != 0) { + sb.setCharAt(6, 'x'); + } + + if ((mode & S_IROTH ) != 0) { + sb.setCharAt(7, 'r'); + } + if ((mode & S_IWOTH ) != 0) { + sb.setCharAt(8, 'w'); + } + if ((mode & S_IXOTH ) != 0) { + sb.setCharAt(9, 'x'); + } + return new String(sb); } - } diff --git a/src/main/org/apache/tools/tar/TarEntry.java b/src/main/org/apache/tools/tar/TarEntry.java index 8ba2f29ff..8dba8e324 100644 --- a/src/main/org/apache/tools/tar/TarEntry.java +++ b/src/main/org/apache/tools/tar/TarEntry.java @@ -452,6 +452,15 @@ public class TarEntry implements TarConstants { } /** + * Get this entry's mode. + * + * @return This entry's mode. + */ + public int getMode() { + return this.mode; + } + + /** * Get this entry's file size. * * @return This entry's file size.