refinement (see extra mail to list). PR: 10755 Submitted by: Antoine Levy-Lambert <levylambert at tiscali-dsl dot de> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273848 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -19,6 +19,9 @@ Changes that could break older environments: | |||||
| * <xmlproperty> will no longer fail if the file to be loaded doesn't exist. | * <xmlproperty> will no longer fail if the file to be loaded doesn't exist. | ||||
| * ZipScanner#getIncludedFiles will now return the names of the ZipEntries | |||||
| that have been matched instead of the name of the archive. | |||||
| Fixed bugs: | Fixed bugs: | ||||
| ----------- | ----------- | ||||
| * <translate> was not ignoring comment lines. | * <translate> was not ignoring comment lines. | ||||
| @@ -57,6 +57,7 @@ package org.apache.tools.ant; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.selectors.FileSelector; | import org.apache.tools.ant.types.selectors.FileSelector; | ||||
| import org.apache.tools.ant.types.selectors.SelectorScanner; | import org.apache.tools.ant.types.selectors.SelectorScanner; | ||||
| import org.apache.tools.ant.types.selectors.SelectorUtils; | import org.apache.tools.ant.types.selectors.SelectorUtils; | ||||
| @@ -149,7 +150,7 @@ import org.apache.tools.ant.util.FileUtils; | |||||
| * @author Magesh Umasankar | * @author Magesh Umasankar | ||||
| * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> | * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> | ||||
| */ | */ | ||||
| public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| public class DirectoryScanner implements ResourceScanner, SelectorScanner { | |||||
| /** | /** | ||||
| * Patterns which should be excluded by default. | * Patterns which should be excluded by default. | ||||
| @@ -201,6 +202,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| */ | */ | ||||
| protected Vector filesIncluded; | protected Vector filesIncluded; | ||||
| /** | |||||
| * the same as filesIncluded, but in terms of Resource | |||||
| */ | |||||
| private Vector filesIncludedR; | |||||
| /** The files which did not match any includes or selectors. */ | /** The files which did not match any includes or selectors. */ | ||||
| protected Vector filesNotIncluded; | protected Vector filesNotIncluded; | ||||
| @@ -214,6 +220,10 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| * and were selected. | * and were selected. | ||||
| */ | */ | ||||
| protected Vector dirsIncluded; | protected Vector dirsIncluded; | ||||
| /** The directories which matched at least one include and no excludes | |||||
| * and were selected, as resources | |||||
| */ | |||||
| private Vector dirsIncludedR; | |||||
| /** The directories which were found and did not match any includes. */ | /** The directories which were found and did not match any includes. */ | ||||
| protected Vector dirsNotIncluded; | protected Vector dirsNotIncluded; | ||||
| @@ -545,10 +555,12 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| } | } | ||||
| filesIncluded = new Vector(); | filesIncluded = new Vector(); | ||||
| filesIncludedR = new Vector(); | |||||
| filesNotIncluded = new Vector(); | filesNotIncluded = new Vector(); | ||||
| filesExcluded = new Vector(); | filesExcluded = new Vector(); | ||||
| filesDeselected = new Vector(); | filesDeselected = new Vector(); | ||||
| dirsIncluded = new Vector(); | dirsIncluded = new Vector(); | ||||
| dirsIncludedR = new Vector(); | |||||
| dirsNotIncluded = new Vector(); | dirsNotIncluded = new Vector(); | ||||
| dirsExcluded = new Vector(); | dirsExcluded = new Vector(); | ||||
| dirsDeselected = new Vector(); | dirsDeselected = new Vector(); | ||||
| @@ -557,6 +569,10 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| if (!isExcluded("")) { | if (!isExcluded("")) { | ||||
| if (isSelected("",basedir)) { | if (isSelected("",basedir)) { | ||||
| dirsIncluded.addElement(""); | dirsIncluded.addElement(""); | ||||
| dirsIncludedR.addElement(new Resource("", true, | |||||
| basedir | |||||
| .lastModified(), | |||||
| true)); | |||||
| } else { | } else { | ||||
| dirsDeselected.addElement(""); | dirsDeselected.addElement(""); | ||||
| } | } | ||||
| @@ -675,6 +691,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| if (!isExcluded(name)) { | if (!isExcluded(name)) { | ||||
| if (isSelected(name,file)) { | if (isSelected(name,file)) { | ||||
| dirsIncluded.addElement(name); | dirsIncluded.addElement(name); | ||||
| dirsIncludedR.addElement(new Resource(name, | |||||
| true, | |||||
| file | |||||
| .lastModified(), | |||||
| true)); | |||||
| if (fast) { | if (fast) { | ||||
| scandir(file, name + File.separator, fast); | scandir(file, name + File.separator, fast); | ||||
| } | } | ||||
| @@ -708,6 +729,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| if (!isExcluded(name)) { | if (!isExcluded(name)) { | ||||
| if (isSelected(name,file)) { | if (isSelected(name,file)) { | ||||
| filesIncluded.addElement(name); | filesIncluded.addElement(name); | ||||
| filesIncludedR.addElement(new Resource(name, | |||||
| true, | |||||
| file | |||||
| .lastModified(), | |||||
| false)); | |||||
| } else { | } else { | ||||
| everythingIncluded = false; | everythingIncluded = false; | ||||
| filesDeselected.addElement(name); | filesDeselected.addElement(name); | ||||
| @@ -810,6 +836,26 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| } | } | ||||
| return files; | return files; | ||||
| } | } | ||||
| /** | |||||
| * Returns the resources of the files which matched at least one | |||||
| * of the include patterns and none of the exclude patterns. The | |||||
| * names are relative to the base directory. | |||||
| * | |||||
| * @return resource information for the files which matched at | |||||
| * least one of the include patterns and none of the exclude | |||||
| * patterns. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource[] getIncludedFileResources() { | |||||
| int count = filesIncludedR.size(); | |||||
| Resource[] resources = new Resource[count]; | |||||
| for (int i = 0; i < count; i++) { | |||||
| resources[i] = | |||||
| (Resource) ((Resource) filesIncludedR.elementAt(i)).clone(); | |||||
| } | |||||
| return resources; | |||||
| } | |||||
| /** | /** | ||||
| * Returns the names of the files which matched none of the include | * Returns the names of the files which matched none of the include | ||||
| @@ -890,6 +936,25 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| return directories; | return directories; | ||||
| } | } | ||||
| /** | |||||
| * Returns the resource object for the directories which matched | |||||
| * at least one of the include patterns and none of the exclude | |||||
| * patterns. The names are relative to the base directory. | |||||
| * | |||||
| * @return the names of the directories which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource[] getIncludedDirectoryResources() { | |||||
| int count = dirsIncludedR.size(); | |||||
| Resource[] directories = new Resource[count]; | |||||
| for (int i = 0; i < count; i++) { | |||||
| directories[i] = | |||||
| (Resource) ((Resource) dirsIncludedR.elementAt(i)).clone(); | |||||
| } | |||||
| return directories; | |||||
| } | |||||
| /** | /** | ||||
| * Returns the names of the directories which matched none of the include | * Returns the names of the directories which matched none of the include | ||||
| * patterns. The names are relative to the base directory. This involves | * patterns. The names are relative to the base directory. This involves | ||||
| @@ -968,4 +1033,21 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||||
| } | } | ||||
| excludes = newExcludes; | excludes = newExcludes; | ||||
| } | } | ||||
| /** | |||||
| * @param name path name of the file relative to the dir attribute. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource getResource(String name) { | |||||
| File f = null; | |||||
| if (basedir != null) { | |||||
| f = new File(basedir, name); | |||||
| } else { | |||||
| f = new File(name); | |||||
| } | |||||
| return new Resource(name, f.exists(), f.lastModified(), | |||||
| f.isDirectory()); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,85 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * 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 | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * 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 | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceFactory; | |||||
| /** | |||||
| * Extends the FileScanner concept to {@link | |||||
| * org.apache.tools.ant.types.Resource Resources}. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public interface ResourceScanner extends FileScanner, ResourceFactory { | |||||
| /** | |||||
| * Returns resources for the directories which matched at least | |||||
| * one of the include patterns and none of the exclude patterns. | |||||
| * | |||||
| * @return resources for the directories which matched at least | |||||
| * one of the include patterns and none of the exclude patterns. | |||||
| */ | |||||
| Resource[] getIncludedDirectoryResources(); | |||||
| /** | |||||
| * Returns resources for the files which matched at least one of | |||||
| * the include patterns and none of the exclude patterns. | |||||
| * | |||||
| * @return the names of the files which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| */ | |||||
| Resource[] getIncludedFileResources(); | |||||
| } | |||||
| @@ -68,9 +68,10 @@ import java.util.Enumeration; | |||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.FileScanner; | |||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.ResourceScanner; | |||||
| import org.apache.tools.ant.types.EnumeratedAttribute; | import org.apache.tools.ant.types.EnumeratedAttribute; | ||||
| import org.apache.tools.ant.types.FileSet; | |||||
| import org.apache.tools.ant.types.ZipFileSet; | import org.apache.tools.ant.types.ZipFileSet; | ||||
| import org.apache.tools.zip.ZipOutputStream; | import org.apache.tools.zip.ZipOutputStream; | ||||
| @@ -521,7 +522,8 @@ public class Jar extends Zip { | |||||
| * already); false if archive creation should proceed | * already); false if archive creation should proceed | ||||
| * @exception BuildException if it likes | * @exception BuildException if it likes | ||||
| */ | */ | ||||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) | |||||
| protected boolean isUpToDate(ResourceScanner[] scanners, | |||||
| FileSet[] fss, File zipFile) | |||||
| throws BuildException { | throws BuildException { | ||||
| // need to handle manifest as a special check | // need to handle manifest as a special check | ||||
| if (configuredManifest != null || manifestFile == null) { | if (configuredManifest != null || manifestFile == null) { | ||||
| @@ -562,7 +564,7 @@ public class Jar extends Zip { | |||||
| } else if (manifestFile.lastModified() > zipFile.lastModified()) { | } else if (manifestFile.lastModified() > zipFile.lastModified()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return super.isUpToDate(scanners, zipFile); | |||||
| return super.isUpToDate(scanners, fss, zipFile); | |||||
| } | } | ||||
| protected boolean createEmptyZip(File zipFile) { | protected boolean createEmptyZip(File zipFile) { | ||||
| @@ -585,6 +587,7 @@ public class Jar extends Zip { | |||||
| manifest = null; | manifest = null; | ||||
| configuredManifest = savedConfiguredManifest; | configuredManifest = savedConfiguredManifest; | ||||
| filesetManifest = null; | filesetManifest = null; | ||||
| originalManifest = null; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
| * | * | ||||
| * Copyright (c) 2000-2002 The Apache Software Foundation. All rights | |||||
| * Copyright (c) 2000-2003 The Apache Software Foundation. All rights | |||||
| * reserved. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| @@ -67,18 +67,25 @@ import java.util.Stack; | |||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import java.util.zip.CRC32; | import java.util.zip.CRC32; | ||||
| import java.util.zip.ZipInputStream; | import java.util.zip.ZipInputStream; | ||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
| import org.apache.tools.ant.FileScanner; | import org.apache.tools.ant.FileScanner; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.ResourceScanner; | |||||
| import org.apache.tools.ant.types.EnumeratedAttribute; | import org.apache.tools.ant.types.EnumeratedAttribute; | ||||
| import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
| import org.apache.tools.ant.types.PatternSet; | import org.apache.tools.ant.types.PatternSet; | ||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceFactory; | |||||
| import org.apache.tools.ant.types.ZipFileSet; | import org.apache.tools.ant.types.ZipFileSet; | ||||
| import org.apache.tools.ant.types.ZipScanner; | import org.apache.tools.ant.types.ZipScanner; | ||||
| import org.apache.tools.ant.util.FileNameMapper; | |||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.ant.util.GlobPatternMapper; | |||||
| import org.apache.tools.ant.util.IdentityMapper; | |||||
| import org.apache.tools.ant.util.MergingMapper; | import org.apache.tools.ant.util.MergingMapper; | ||||
| import org.apache.tools.ant.util.SourceFileScanner; | |||||
| import org.apache.tools.ant.util.SourceSelector; | |||||
| import org.apache.tools.zip.ZipEntry; | import org.apache.tools.zip.ZipEntry; | ||||
| import org.apache.tools.zip.ZipOutputStream; | import org.apache.tools.zip.ZipOutputStream; | ||||
| @@ -93,9 +100,11 @@ import org.apache.tools.zip.ZipOutputStream; | |||||
| * | * | ||||
| * @ant.task category="packaging" | * @ant.task category="packaging" | ||||
| */ | */ | ||||
| public class Zip extends MatchingTask { | |||||
| public class Zip extends MatchingTask implements ResourceFactory { | |||||
| protected File zipFile; | protected File zipFile; | ||||
| // use to scan own archive | |||||
| private ZipScanner zs; | |||||
| private File baseDir; | private File baseDir; | ||||
| protected Hashtable entries = new Hashtable(); | protected Hashtable entries = new Hashtable(); | ||||
| private Vector groupfilesets = new Vector(); | private Vector groupfilesets = new Vector(); | ||||
| @@ -117,6 +126,7 @@ public class Zip extends MatchingTask { | |||||
| protected boolean doubleFilePass = false; | protected boolean doubleFilePass = false; | ||||
| protected boolean skipWriting = false; | protected boolean skipWriting = false; | ||||
| private FileUtils fileUtils; | |||||
| /** | /** | ||||
| @@ -331,22 +341,28 @@ public class Zip extends MatchingTask { | |||||
| // Create the scanners to pass to isUpToDate(). | // Create the scanners to pass to isUpToDate(). | ||||
| Vector dss = new Vector(); | Vector dss = new Vector(); | ||||
| Vector vfss = new Vector(); | |||||
| if (baseDir != null) { | if (baseDir != null) { | ||||
| dss.addElement(getDirectoryScanner(baseDir)); | dss.addElement(getDirectoryScanner(baseDir)); | ||||
| FileSet fs = new FileSet(); | |||||
| fs.setDir(baseDir); | |||||
| vfss.addElement(fs); | |||||
| } | } | ||||
| for (int i = 0; i < filesets.size(); i++) { | for (int i = 0; i < filesets.size(); i++) { | ||||
| FileSet fs = (FileSet) filesets.elementAt(i); | FileSet fs = (FileSet) filesets.elementAt(i); | ||||
| dss.addElement (fs.getDirectoryScanner(getProject())); | dss.addElement (fs.getDirectoryScanner(getProject())); | ||||
| vfss.addElement(fs); | |||||
| } | } | ||||
| int dssSize = dss.size(); | int dssSize = dss.size(); | ||||
| FileScanner[] scanners = new FileScanner[dssSize]; | |||||
| ResourceScanner[] scanners = new ResourceScanner[dssSize]; | |||||
| dss.copyInto(scanners); | dss.copyInto(scanners); | ||||
| FileSet [] fss = new FileSet[dssSize]; | |||||
| vfss.copyInto(fss); | |||||
| boolean success = false; | boolean success = false; | ||||
| try { | try { | ||||
| // quick exit if the target is up to date | // quick exit if the target is up to date | ||||
| // can also handle empty archives | // can also handle empty archives | ||||
| if (isUpToDate(scanners, zipFile)) { | |||||
| if (isUpToDate(scanners, fss, zipFile)) { | |||||
| return; | return; | ||||
| } | } | ||||
| @@ -642,6 +658,15 @@ public class Zip extends MatchingTask { | |||||
| return true; | return true; | ||||
| } | } | ||||
| public Resource getResource(String name) { | |||||
| if (zs==null) { | |||||
| zs=new ZipScanner(); | |||||
| // set the task of the zip scanner so that it can log properly | |||||
| zs.setTask(this); | |||||
| zs.setSrc(zipFile); | |||||
| } | |||||
| return zs.getResource(name); | |||||
| } | |||||
| /** | /** | ||||
| * Check whether the archive is up-to-date; and handle behavior | * Check whether the archive is up-to-date; and handle behavior | ||||
| @@ -652,8 +677,17 @@ public class Zip extends MatchingTask { | |||||
| * already); false if archive creation should proceed | * already); false if archive creation should proceed | ||||
| * @exception BuildException if it likes | * @exception BuildException if it likes | ||||
| */ | */ | ||||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) | |||||
| protected boolean isUpToDate(ResourceScanner[] scanners, | |||||
| FileSet[] fss, File zipFile) | |||||
| throws BuildException { | throws BuildException { | ||||
| Resource[][] resourceNames = grabResources(scanners); | |||||
| for (int counter = 0;counter < scanners.length; counter++){ | |||||
| for (int j=0; j < resourceNames[counter].length;j++) { | |||||
| log("resource from scanner " + counter + " " + j + " name : " | |||||
| + resourceNames[counter][j].getName(), Project.MSG_DEBUG); | |||||
| } | |||||
| } | |||||
| String[][] fileNames = grabFileNames(scanners); | String[][] fileNames = grabFileNames(scanners); | ||||
| File[] files = grabFiles(scanners, fileNames); | File[] files = grabFiles(scanners, fileNames); | ||||
| if (files.length == 0) { | if (files.length == 0) { | ||||
| @@ -681,17 +715,39 @@ public class Zip extends MatchingTask { | |||||
| return false; | return false; | ||||
| } | } | ||||
| SourceFileScanner sfs = new SourceFileScanner(this); | |||||
| MergingMapper mm = new MergingMapper(); | |||||
| mm.setTo(zipFile.getAbsolutePath()); | |||||
| for (int i = 0; i < scanners.length; i++) { | for (int i = 0; i < scanners.length; i++) { | ||||
| if (sfs.restrict(fileNames[i], scanners[i].getBasedir(), null, | |||||
| mm).length > 0) { | |||||
| return false; | |||||
| boolean result=false; | |||||
| FileNameMapper myMapper = new IdentityMapper(); | |||||
| if (fss[i] instanceof ZipFileSet) { | |||||
| ZipFileSet zfs = (ZipFileSet) fss[i]; | |||||
| if (zfs.getFullpath() != null | |||||
| && !zfs.getFullpath().equals("") ) { | |||||
| // in this case all files from origin map to | |||||
| // the fullPath attribute of the zipfileset at | |||||
| // destination | |||||
| MergingMapper fm = new MergingMapper(); | |||||
| fm.setTo(zfs.getFullpath()); | |||||
| myMapper = fm; | |||||
| } else if (zfs.getPrefix() != null | |||||
| && !zfs.getPrefix().equals("")) { | |||||
| GlobPatternMapper gm=new GlobPatternMapper(); | |||||
| gm.setFrom("*"); | |||||
| gm.setTo(zfs.getPrefix() + "*"); | |||||
| myMapper = gm; | |||||
| } | |||||
| } | |||||
| Resource[] newerSources = | |||||
| SourceSelector.selectOutOfDateSources(this, | |||||
| resourceNames[i], | |||||
| myMapper, this); | |||||
| result = (newerSources.length == 0); | |||||
| if (!result) { | |||||
| return result; | |||||
| } | } | ||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| protected static File[] grabFiles(FileScanner[] scanners) { | protected static File[] grabFiles(FileScanner[] scanners) { | ||||
| @@ -723,6 +779,24 @@ public class Zip extends MatchingTask { | |||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| /** | |||||
| * | |||||
| * @param scanners here are expected ResourceScanner arguments | |||||
| * @return double dimensional array of resources | |||||
| */ | |||||
| protected static Resource[][] grabResources(ResourceScanner[] scanners) { | |||||
| Resource[][] result = new Resource[scanners.length][]; | |||||
| for (int i = 0; i < scanners.length; i++) { | |||||
| Resource[] files = scanners[i].getIncludedFileResources(); | |||||
| Resource[] directories = | |||||
| scanners[i].getIncludedDirectoryResources(); | |||||
| result[i] = new Resource[files.length + directories.length]; | |||||
| System.arraycopy(files, 0, result[i], 0, files.length); | |||||
| System.arraycopy(directories, 0, result[i], files.length, | |||||
| directories.length); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | /** | ||||
| * @deprecated use four-arg version instead. | * @deprecated use four-arg version instead. | ||||
| @@ -0,0 +1,165 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * 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 | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * 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 | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| /** | |||||
| * describes a File or a ZipEntry | |||||
| * | |||||
| * this class is meant to be used by classes needing to record path | |||||
| * and date/time information about a file, a zip entry or some similar | |||||
| * resource (URL, archive in a version control repository, ...) | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public class Resource implements Cloneable { | |||||
| private String name = null; | |||||
| private boolean exists = true; | |||||
| private long lastmodified = 0; | |||||
| private boolean directory = false; | |||||
| /** | |||||
| * default constructor | |||||
| */ | |||||
| public Resource() { | |||||
| } | |||||
| /** | |||||
| * only sets the name. | |||||
| * | |||||
| * <p>This is a dummy, used for not existing resources.</p> | |||||
| */ | |||||
| public Resource(String name) { | |||||
| this(name, false, 0, false); | |||||
| } | |||||
| /** | |||||
| * sets the name, lastmodified flag, and exists flag | |||||
| */ | |||||
| public Resource(String name, boolean exists, long lastmodified) { | |||||
| this(name, exists, lastmodified, false); | |||||
| } | |||||
| public Resource(String name, boolean exists, long lastmodified, | |||||
| boolean directory) { | |||||
| this.name = name; | |||||
| this.exists = exists; | |||||
| this.lastmodified = lastmodified; | |||||
| this.directory = directory; | |||||
| } | |||||
| /** | |||||
| * name attribute will contain the path of a file relative to the | |||||
| * root directory of its fileset or the recorded path of a zip | |||||
| * entry. | |||||
| * | |||||
| * <p>example for a file with fullpath /var/opt/adm/resource.txt | |||||
| * in a file set with root dir /var/opt it will be | |||||
| * adm/resource.txt.</p> | |||||
| */ | |||||
| public String getName() { | |||||
| return name; | |||||
| } | |||||
| public void setName(String name) { | |||||
| this.name = name; | |||||
| } | |||||
| /** | |||||
| * the exists attribute tells whether a file exists | |||||
| */ | |||||
| public boolean isExists() { | |||||
| return exists; | |||||
| } | |||||
| public void setExists(boolean exists) { | |||||
| this.exists = exists; | |||||
| } | |||||
| /** | |||||
| * tells the modification time in milliseconds since 01.01.1970 of | |||||
| * | |||||
| * @return 0 if the resource does not exist to mirror the behavior | |||||
| * of {@link java.io.File File}. | |||||
| */ | |||||
| public long getLastModified() { | |||||
| return !exists || lastmodified < 0 ? 0 : lastmodified; | |||||
| } | |||||
| public void setLastModified(long lastmodified) { | |||||
| this.lastmodified = lastmodified; | |||||
| } | |||||
| /** | |||||
| * tells if the resource is a directory | |||||
| * @return boolean flag indicating if the resource is a directory | |||||
| */ | |||||
| public boolean isDirectory() { | |||||
| return directory; | |||||
| } | |||||
| public void setDirectory(boolean directory) { | |||||
| this.directory = directory; | |||||
| } | |||||
| /** | |||||
| * @return copy of this | |||||
| */ | |||||
| public Object clone() { | |||||
| try { | |||||
| return super.clone(); | |||||
| } catch (CloneNotSupportedException e) { | |||||
| throw new Error("CloneNotSupportedException for a " | |||||
| + "Clonable Resource caught?"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,73 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * 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 | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * 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 | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| /** | |||||
| * this interface should be implemented by classes (Scanners) needing | |||||
| * to deliver information about resources. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public interface ResourceFactory { | |||||
| /** | |||||
| * Query a resource (file, zipentry, ...) by name | |||||
| * | |||||
| * @param Name relative path of the resource about which | |||||
| * information is sought | |||||
| * @return instance of Resource; the exists attribute of Resource | |||||
| * will tell whether the sought resource exists | |||||
| */ | |||||
| Resource getResource(String name); | |||||
| } | |||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
| * | * | ||||
| * Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||||
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights | |||||
| * reserved. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| @@ -55,18 +55,24 @@ | |||||
| package org.apache.tools.ant.types; | package org.apache.tools.ant.types; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | |||||
| import java.io.IOException; | |||||
| import java.util.Vector; | |||||
| import java.util.zip.ZipInputStream; | |||||
| import java.util.zip.ZipEntry; | |||||
| import java.util.zip.ZipException; | |||||
| import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.Task; | |||||
| /** | /** | ||||
| * ZipScanner accesses the pattern matching algorithm in DirectoryScanner, | * ZipScanner accesses the pattern matching algorithm in DirectoryScanner, | ||||
| * which are protected methods that can only be accessed by subclassing. | * which are protected methods that can only be accessed by subclassing. | ||||
| * | * | ||||
| * This implementation of FileScanner defines getIncludedFiles to return | * This implementation of FileScanner defines getIncludedFiles to return | ||||
| * only the Zip File which is being scanned, not the matching Zip entries. | |||||
| * Arguably, it should return the matching entries, however this would | |||||
| * complicate existing code which assumes that FileScanners return a | |||||
| * set of file system files that can be accessed directly. | |||||
| * | |||||
| * the matching Zip entries. | |||||
| * | |||||
| * @author Don Ferguson <a href="mailto:don@bea.com">don@bea.com</a> | * @author Don Ferguson <a href="mailto:don@bea.com">don@bea.com</a> | ||||
| */ | */ | ||||
| public class ZipScanner extends DirectoryScanner { | public class ZipScanner extends DirectoryScanner { | ||||
| @@ -75,35 +81,84 @@ public class ZipScanner extends DirectoryScanner { | |||||
| * The zip file which should be scanned. | * The zip file which should be scanned. | ||||
| */ | */ | ||||
| protected File srcFile; | protected File srcFile; | ||||
| /** | |||||
| * The current task, used to report errors, ... | |||||
| */ | |||||
| private Task task; | |||||
| /** | |||||
| * to record the last scanned zip file with its modification date | |||||
| */ | |||||
| private Resource lastScannedResource; | |||||
| /** | |||||
| * record list of all zip entries | |||||
| */ | |||||
| private Vector myentries; | |||||
| /** | /** | ||||
| * Sets the srcFile for scanning. This is the jar or zip file that is scanned | |||||
| * for matching entries. | |||||
| * Sets the srcFile for scanning. This is the jar or zip file that | |||||
| * is scanned for matching entries. | |||||
| * | * | ||||
| * @param srcFile the (non-null) zip file name for scanning | * @param srcFile the (non-null) zip file name for scanning | ||||
| */ | */ | ||||
| public void setSrc(File srcFile) { | public void setSrc(File srcFile) { | ||||
| this.srcFile = srcFile; | this.srcFile = srcFile; | ||||
| } | } | ||||
| /** | |||||
| * Sets the current task. This is used to provide proper logging | |||||
| * for exceptions | |||||
| * | |||||
| * @param task the current task | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public void setTask(Task task) { | |||||
| this.task = task; | |||||
| } | |||||
| /** | /** | ||||
| * Returns the zip file itself, not the matching entries within the zip file. | |||||
| * This keeps the uptodate test in the Zip task simple; otherwise we'd need | |||||
| * to treat zip filesets specially. | |||||
| * Returns the names of the files which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| * The names are relative to the base directory. | |||||
| * | * | ||||
| * @return the source file from which entries will be extracted. | |||||
| * @return the names of the files which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| */ | */ | ||||
| public String[] getIncludedFiles() { | public String[] getIncludedFiles() { | ||||
| String[] result = new String[1]; | |||||
| result[0] = srcFile.getAbsolutePath(); | |||||
| return result; | |||||
| Vector myvector = new Vector(); | |||||
| // first check if the archive needs to be scanned again | |||||
| scanme(); | |||||
| for (int counter = 0; counter < myentries.size(); counter++) { | |||||
| Resource myresource= (Resource) myentries.elementAt(counter); | |||||
| if (!myresource.isDirectory() && match(myresource.getName())) { | |||||
| myvector.addElement(myresource.getName()); | |||||
| } | |||||
| } | |||||
| String[] files = new String[myvector.size()]; | |||||
| myvector.copyInto(files); | |||||
| return files; | |||||
| } | } | ||||
| /** | /** | ||||
| * Returns an empty list of directories to create. | |||||
| * Returns the names of the directories which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| * The names are relative to the base directory. | |||||
| * | |||||
| * @return the names of the directories which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| */ | */ | ||||
| public String[] getIncludedDirectories() { | public String[] getIncludedDirectories() { | ||||
| return new String[0]; | |||||
| Vector myvector=new Vector(); | |||||
| // first check if the archive needs to be scanned again | |||||
| scanme(); | |||||
| for (int counter = 0; counter < myentries.size(); counter++) { | |||||
| Resource myresource = (Resource) myentries.elementAt(counter); | |||||
| if (myresource.isDirectory() && match(myresource.getName())) { | |||||
| myvector.addElement(myresource.getName()); | |||||
| } | |||||
| } | |||||
| String[] files = new String[myvector.size()]; | |||||
| myvector.copyInto(files); | |||||
| return files; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -135,4 +190,164 @@ public class ZipScanner extends DirectoryScanner { | |||||
| return isIncluded(vpath) && !isExcluded(vpath); | return isIncluded(vpath) && !isExcluded(vpath); | ||||
| } | } | ||||
| /** | |||||
| * Returns the resources of the files which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| * The names are relative to the base directory. | |||||
| * | |||||
| * @return resource information for the files which matched at | |||||
| * least one of the include patterns and none of the exclude | |||||
| * patterns. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource[] getIncludedFileResources() { | |||||
| Vector myvector = new Vector(); | |||||
| // first check if the archive needs to be scanned again | |||||
| scanme(); | |||||
| for (int counter = 0; counter < myentries.size(); counter++) { | |||||
| Resource myresource = (Resource) myentries.elementAt(counter); | |||||
| if (!myresource.isDirectory() && match(myresource.getName())) { | |||||
| myvector.addElement(myresource.clone()); | |||||
| } | |||||
| } | |||||
| Resource[] resources = new Resource[myvector.size()]; | |||||
| myvector.copyInto(resources); | |||||
| return resources; | |||||
| } | |||||
| /** | |||||
| * Returns the resources of the files which matched at least one of the | |||||
| * include patterns and none of the exclude patterns. | |||||
| * The names are relative to the base directory. | |||||
| * | |||||
| * @return resource information for the files which matched at | |||||
| * least one of the include patterns and none of the exclude | |||||
| * patterns. | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource[] getIncludedDirectoryResources() { | |||||
| Vector myvector = new Vector(); | |||||
| // first check if the archive needs to be scanned again | |||||
| scanme(); | |||||
| for (int counter = 0; counter < myentries.size(); counter++) { | |||||
| Resource myresource = (Resource) myentries.elementAt(counter); | |||||
| if (myresource.isDirectory() && match(myresource.getName())) { | |||||
| myvector.add(myresource.clone()); | |||||
| } | |||||
| } | |||||
| Resource[] resources = new Resource[myvector.size()]; | |||||
| myvector.copyInto(resources); | |||||
| return resources; | |||||
| } | |||||
| /** | |||||
| * @param name path name of the file sought in the archive | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource getResource(String name) { | |||||
| // first check if the archive needs to be scanned again | |||||
| scanme(); | |||||
| for (int counter = 0; counter < myentries.size(); counter++) { | |||||
| Resource myresource=(Resource)myentries.elementAt(counter); | |||||
| if (myresource.getName().equals(name)) { | |||||
| return myresource; | |||||
| } | |||||
| } | |||||
| return new Resource(name); | |||||
| } | |||||
| /** | |||||
| * if the datetime of the archive did not change since | |||||
| * lastScannedResource was initialized returns immediately else if | |||||
| * the archive has not been scanned yet, then all the zip entries | |||||
| * are put into the vector myentries as a vector of the resource | |||||
| * type | |||||
| */ | |||||
| private void scanme() { | |||||
| Resource thisresource = new Resource(srcFile.getAbsolutePath(), | |||||
| srcFile.exists(), | |||||
| srcFile.lastModified()); | |||||
| // spare scanning again and again | |||||
| if (lastScannedResource != null | |||||
| && lastScannedResource.getName().equals(thisresource.getName()) | |||||
| && lastScannedResource.getLastModified() | |||||
| == thisresource.getLastModified()) { | |||||
| return; | |||||
| } | |||||
| Vector vResult = new Vector(); | |||||
| if (task != null) { | |||||
| task.log("checking zip entries: " + srcFile, Project.MSG_VERBOSE); | |||||
| } | |||||
| ZipEntry entry = null; | |||||
| ZipInputStream in = null; | |||||
| myentries = new Vector(); | |||||
| try { | |||||
| try { | |||||
| in = new ZipInputStream(new FileInputStream(srcFile)); | |||||
| if (task != null) { | |||||
| task.log("opening input stream from " + srcFile, | |||||
| Project.MSG_DEBUG); | |||||
| } | |||||
| } catch (IOException ex) { | |||||
| // XXX - throw a BuildException instead ?? | |||||
| if (task != null) { | |||||
| task.log("problem opening "+srcFile,Project.MSG_ERR); | |||||
| } | |||||
| } | |||||
| while (true) { | |||||
| try { | |||||
| entry = in.getNextEntry(); | |||||
| if (entry == null) { | |||||
| break; | |||||
| } | |||||
| myentries.add(new Resource(entry.getName(), | |||||
| true, | |||||
| entry.getTime(), | |||||
| entry.isDirectory())); | |||||
| if (task != null) { | |||||
| task.log("adding entry " + entry.getName() + " from " | |||||
| + srcFile, Project.MSG_DEBUG); | |||||
| } | |||||
| } catch (ZipException ex) { | |||||
| // XXX - throw a BuildException instead ?? | |||||
| if (task != null ) { | |||||
| task.log("problem reading " + srcFile, | |||||
| Project.MSG_ERR); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| // XXX - throw a BuildException instead ?? | |||||
| if (task != null) { | |||||
| task.log("problem reading zip entry from " + srcFile, | |||||
| Project.MSG_ERR); | |||||
| } | |||||
| } | |||||
| } | |||||
| } finally { | |||||
| if (in != null) { | |||||
| try { | |||||
| in.close(); | |||||
| if (task != null) { | |||||
| task.log("closing input stream from " + srcFile, | |||||
| Project.MSG_DEBUG); | |||||
| } | |||||
| } catch (IOException ex) { | |||||
| if (task != null) { | |||||
| task.log("problem closing input stream from " | |||||
| + srcFile, Project.MSG_ERR); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // record data about the last scanned resource | |||||
| lastScannedResource = thisresource; | |||||
| } | |||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
| * | * | ||||
| * Copyright (c) 2000-2002 The Apache Software Foundation. All rights | |||||
| * Copyright (c) 2000-2003 The Apache Software Foundation. All rights | |||||
| * reserved. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| @@ -58,6 +58,8 @@ import java.io.File; | |||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.types.ResourceFactory; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.taskdefs.condition.Os; | import org.apache.tools.ant.taskdefs.condition.Os; | ||||
| /** | /** | ||||
| @@ -70,11 +72,12 @@ import org.apache.tools.ant.taskdefs.condition.Os; | |||||
| * | * | ||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | ||||
| */ | */ | ||||
| public class SourceFileScanner { | |||||
| public class SourceFileScanner implements ResourceFactory { | |||||
| protected Task task; | protected Task task; | ||||
| private FileUtils fileUtils; | private FileUtils fileUtils; | ||||
| private File destDir; // base directory of the fileset | |||||
| /** | /** | ||||
| * @param task The task we should log messages through | * @param task The task we should log messages through | ||||
| @@ -97,71 +100,26 @@ public class SourceFileScanner { | |||||
| */ | */ | ||||
| public String[] restrict(String[] files, File srcDir, File destDir, | public String[] restrict(String[] files, File srcDir, File destDir, | ||||
| FileNameMapper mapper) { | FileNameMapper mapper) { | ||||
| long now = (new java.util.Date()).getTime(); | |||||
| StringBuffer targetList = new StringBuffer(); | |||||
| /* | |||||
| If we're on Windows, we have to munge the time up to 2 secs to | |||||
| be able to check file modification times. | |||||
| (Windows has a max resolution of two secs for modification times) | |||||
| Actually this is a feature of the FAT file system, NTFS does | |||||
| not have it, so if we could reliably passively test for an NTFS | |||||
| file systems we could turn this off... | |||||
| */ | |||||
| if (Os.isFamily("windows")) { | |||||
| now += 2000; | |||||
| } | |||||
| // record destdir for later use in getResource | |||||
| this.destDir = destDir; | |||||
| Vector v = new Vector(); | Vector v = new Vector(); | ||||
| for (int i = 0; i < files.length; i++) { | for (int i = 0; i < files.length; i++) { | ||||
| String[] targets = mapper.mapFileName(files[i]); | |||||
| if (targets == null || targets.length == 0) { | |||||
| task.log(files[i] + " skipped - don\'t know how to handle it", | |||||
| Project.MSG_VERBOSE); | |||||
| continue; | |||||
| } | |||||
| File src = fileUtils.resolveFile(srcDir, files[i]); | File src = fileUtils.resolveFile(srcDir, files[i]); | ||||
| if (src.lastModified() > now) { | |||||
| task.log("Warning: " + files[i] + " modified in the future.", | |||||
| Project.MSG_WARN); | |||||
| } | |||||
| boolean added = false; | |||||
| targetList.setLength(0); | |||||
| for (int j = 0; !added && j < targets.length; j++) { | |||||
| File dest = fileUtils.resolveFile(destDir, targets[j]); | |||||
| if (!dest.exists()) { | |||||
| task.log(files[i] + " added as " + dest.getAbsolutePath() | |||||
| + " doesn\'t exist.", Project.MSG_VERBOSE); | |||||
| v.addElement(files[i]); | |||||
| added = true; | |||||
| } else if (src.lastModified() > dest.lastModified()) { | |||||
| task.log(files[i] + " added as " + dest.getAbsolutePath() | |||||
| + " is outdated.", Project.MSG_VERBOSE); | |||||
| v.addElement(files[i]); | |||||
| added = true; | |||||
| } else { | |||||
| if (targetList.length() > 0) { | |||||
| targetList.append(", "); | |||||
| } | |||||
| targetList.append(dest.getAbsolutePath()); | |||||
| } | |||||
| } | |||||
| if (!added) { | |||||
| task.log(files[i] + " omitted as " + targetList.toString() | |||||
| + (targets.length == 1 ? " is" : " are ") | |||||
| + " up to date.", Project.MSG_VERBOSE); | |||||
| } | |||||
| v.addElement(new Resource(files[i], src.exists(), | |||||
| src.lastModified(), src.isDirectory())); | |||||
| } | |||||
| Resource[] sourceresources= new Resource[v.size()]; | |||||
| v.copyInto(sourceresources); | |||||
| // build the list of sources which are out of date with | |||||
| // respect to the target | |||||
| Resource[] outofdate = | |||||
| SourceSelector.selectOutOfDateSources(task, sourceresources, | |||||
| mapper, this); | |||||
| String[] result = new String[outofdate.length]; | |||||
| for (int counter=0; counter < outofdate.length; counter++) { | |||||
| result[counter] = outofdate[counter].getName(); | |||||
| } | } | ||||
| String[] result = new String[v.size()]; | |||||
| v.copyInto(result); | |||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -179,4 +137,18 @@ public class SourceFileScanner { | |||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| /** | |||||
| * returns resource information for a file at destination | |||||
| * @param name relative path of file at destination | |||||
| * @return data concerning a file whose relative path to destDir is name | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public Resource getResource(String name) { | |||||
| File src = fileUtils.resolveFile(destDir, name); | |||||
| return new Resource(name, src.exists(), src.lastModified(), | |||||
| src.isDirectory()); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,160 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * 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 | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * 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 | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.util; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.ProjectComponent; | |||||
| import org.apache.tools.ant.taskdefs.condition.Os; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceFactory; | |||||
| import java.util.Vector; | |||||
| /** | |||||
| * this class provides utilily methods to process resources | |||||
| * | |||||
| * @since Ant 1.5.2 | |||||
| */ | |||||
| public class SourceSelector { | |||||
| /** { | |||||
| * tells which source files should be reprocessed based on the | |||||
| * last modification date of target files | |||||
| * @param logTo where to send (more or less) interesting output | |||||
| * @param source array of resources bearing relative path and last | |||||
| * modification date | |||||
| * @param mapper filename mapper indicating how to find the target | |||||
| * files | |||||
| * @param targets object able to map as a resource a relative path | |||||
| * at <b>destination</b> | |||||
| * @return array containing the source files which need to be | |||||
| * copied or processed, because the targets are out of date or do | |||||
| * not exist | |||||
| */ | |||||
| public static Resource[] selectOutOfDateSources(ProjectComponent logTo, | |||||
| Resource[] source, | |||||
| FileNameMapper mapper, | |||||
| ResourceFactory targets) { | |||||
| long now = (new java.util.Date()).getTime(); | |||||
| StringBuffer targetList = new StringBuffer(); | |||||
| /* | |||||
| If we're on Windows, we have to munge the time up to 2 secs to | |||||
| be able to check file modification times. | |||||
| (Windows has a max resolution of two secs for modification times) | |||||
| Actually this is a feature of the FAT file system, NTFS does | |||||
| not have it, so if we could reliably passively test for an NTFS | |||||
| file systems we could turn this off... | |||||
| */ | |||||
| if (Os.isFamily("windows")) { | |||||
| now += 2000; | |||||
| } | |||||
| Vector vresult = new Vector(); | |||||
| for (int counter = 0; counter < source.length; counter++) { | |||||
| if (source[counter].getLastModified() > now) { | |||||
| logTo.log("Warning: " + source[counter].getName() | |||||
| + " modified in the future.", | |||||
| Project.MSG_WARN); | |||||
| } | |||||
| String[] targetnames = | |||||
| mapper.mapFileName(source[counter].getName()); | |||||
| if (targetnames != null) { | |||||
| boolean added = false; | |||||
| targetList.setLength(0); | |||||
| for (int ctarget = 0; ctarget < targetnames.length; ctarget++) { | |||||
| Resource atarget = | |||||
| targets.getResource(targetnames[ctarget]); | |||||
| // if the target does not exist, or exists and | |||||
| // is older than the source, then we want to | |||||
| // add the resource to what needs to be copied | |||||
| if (!atarget.isExists()) { | |||||
| logTo.log(source[counter].getName() + " added as " | |||||
| + atarget.getName() | |||||
| + " doesn\'t exist.", Project.MSG_VERBOSE); | |||||
| vresult.addElement(source[counter]); | |||||
| added = true; | |||||
| } else if (atarget.getLastModified() | |||||
| < source[counter].getLastModified()) { | |||||
| logTo.log(source[counter].getName() + " added as " | |||||
| + atarget.getName() | |||||
| + " is outdated.", Project.MSG_VERBOSE); | |||||
| vresult.addElement(source[counter]); | |||||
| added = true; | |||||
| } else { | |||||
| if (targetList.length() > 0) { | |||||
| targetList.append(", "); | |||||
| } | |||||
| targetList.append(atarget.getName()); | |||||
| } | |||||
| } | |||||
| if (!added) { | |||||
| logTo.log(source[counter].getName() | |||||
| + " omitted as " + targetList.toString() | |||||
| + (targetnames.length == 1 ? " is" : " are ") | |||||
| + " up to date.", Project.MSG_VERBOSE); | |||||
| } | |||||
| } else { | |||||
| logTo.log(source[counter].getName() | |||||
| + " skipped - don\'t know how to handle it", | |||||
| Project.MSG_VERBOSE); | |||||
| } | |||||
| } | |||||
| Resource[] result= new Resource[vresult.size()]; | |||||
| vresult.copyInto(result); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @@ -653,7 +653,7 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
| | (time.getDate() << 16) | | (time.getDate() << 16) | ||||
| | (time.getHours() << 11) | | (time.getHours() << 11) | ||||
| | (time.getMinutes() << 5) | | (time.getMinutes() << 5) | ||||
| | (time.getSeconds() >> 1); | |||||
| | ((time.getSeconds() + 2) >> 1); | |||||
| byte[] result = new byte[4]; | byte[] result = new byte[4]; | ||||
| result[0] = (byte) ((value & 0xFF)); | result[0] = (byte) ((value & 0xFF)); | ||||
| @@ -119,20 +119,20 @@ public class JarTest extends BuildFileTest { | |||||
| jarModifiedDate, jarFile.lastModified()); | jarModifiedDate, jarFile.lastModified()); | ||||
| } | } | ||||
| public void XtestRecreateWithoutUpdateAdditionalFiles() { | |||||
| public void testRecreateWithoutUpdateAdditionalFiles() { | |||||
| testRecreate("test4", "testRecreateWithoutUpdateAdditionalFiles"); | testRecreate("test4", "testRecreateWithoutUpdateAdditionalFiles"); | ||||
| } | } | ||||
| public void XtestRecreateWithUpdateAdditionalFiles() { | |||||
| public void testRecreateWithUpdateAdditionalFiles() { | |||||
| testRecreate("test4", "testRecreateWithUpdateAdditionalFiles"); | testRecreate("test4", "testRecreateWithUpdateAdditionalFiles"); | ||||
| } | } | ||||
| public void XtestRecreateWithoutUpdateNewerFile() { | |||||
| public void testRecreateWithoutUpdateNewerFile() { | |||||
| testRecreate("testRecreateNewerFileSetup", | testRecreate("testRecreateNewerFileSetup", | ||||
| "testRecreateWithoutUpdateNewerFile"); | "testRecreateWithoutUpdateNewerFile"); | ||||
| } | } | ||||
| public void XtestRecreateWithUpdateNewerFile() { | |||||
| public void testRecreateWithUpdateNewerFile() { | |||||
| testRecreate("testRecreateNewerFileSetup", | testRecreate("testRecreateNewerFileSetup", | ||||
| "testRecreateWithUpdateNewerFile"); | "testRecreateWithUpdateNewerFile"); | ||||
| } | } | ||||