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. | |||
| * ZipScanner#getIncludedFiles will now return the names of the ZipEntries | |||
| that have been matched instead of the name of the archive. | |||
| Fixed bugs: | |||
| ----------- | |||
| * <translate> was not ignoring comment lines. | |||
| @@ -57,6 +57,7 @@ package org.apache.tools.ant; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| 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.SelectorScanner; | |||
| import org.apache.tools.ant.types.selectors.SelectorUtils; | |||
| @@ -149,7 +150,7 @@ import org.apache.tools.ant.util.FileUtils; | |||
| * @author Magesh Umasankar | |||
| * @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. | |||
| @@ -201,6 +202,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| */ | |||
| 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. */ | |||
| protected Vector filesNotIncluded; | |||
| @@ -214,6 +220,10 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| * and were selected. | |||
| */ | |||
| 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. */ | |||
| protected Vector dirsNotIncluded; | |||
| @@ -545,10 +555,12 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| } | |||
| filesIncluded = new Vector(); | |||
| filesIncludedR = new Vector(); | |||
| filesNotIncluded = new Vector(); | |||
| filesExcluded = new Vector(); | |||
| filesDeselected = new Vector(); | |||
| dirsIncluded = new Vector(); | |||
| dirsIncludedR = new Vector(); | |||
| dirsNotIncluded = new Vector(); | |||
| dirsExcluded = new Vector(); | |||
| dirsDeselected = new Vector(); | |||
| @@ -557,6 +569,10 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| if (!isExcluded("")) { | |||
| if (isSelected("",basedir)) { | |||
| dirsIncluded.addElement(""); | |||
| dirsIncludedR.addElement(new Resource("", true, | |||
| basedir | |||
| .lastModified(), | |||
| true)); | |||
| } else { | |||
| dirsDeselected.addElement(""); | |||
| } | |||
| @@ -675,6 +691,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| if (!isExcluded(name)) { | |||
| if (isSelected(name,file)) { | |||
| dirsIncluded.addElement(name); | |||
| dirsIncludedR.addElement(new Resource(name, | |||
| true, | |||
| file | |||
| .lastModified(), | |||
| true)); | |||
| if (fast) { | |||
| scandir(file, name + File.separator, fast); | |||
| } | |||
| @@ -708,6 +729,11 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| if (!isExcluded(name)) { | |||
| if (isSelected(name,file)) { | |||
| filesIncluded.addElement(name); | |||
| filesIncludedR.addElement(new Resource(name, | |||
| true, | |||
| file | |||
| .lastModified(), | |||
| false)); | |||
| } else { | |||
| everythingIncluded = false; | |||
| filesDeselected.addElement(name); | |||
| @@ -810,6 +836,26 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| } | |||
| 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 | |||
| @@ -890,6 +936,25 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| 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 | |||
| * patterns. The names are relative to the base directory. This involves | |||
| @@ -968,4 +1033,21 @@ public class DirectoryScanner implements FileScanner, SelectorScanner { | |||
| } | |||
| 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.ZipFile; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.FileScanner; | |||
| 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.FileSet; | |||
| import org.apache.tools.ant.types.ZipFileSet; | |||
| import org.apache.tools.zip.ZipOutputStream; | |||
| @@ -521,7 +522,8 @@ public class Jar extends Zip { | |||
| * already); false if archive creation should proceed | |||
| * @exception BuildException if it likes | |||
| */ | |||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) | |||
| protected boolean isUpToDate(ResourceScanner[] scanners, | |||
| FileSet[] fss, File zipFile) | |||
| throws BuildException { | |||
| // need to handle manifest as a special check | |||
| if (configuredManifest != null || manifestFile == null) { | |||
| @@ -562,7 +564,7 @@ public class Jar extends Zip { | |||
| } else if (manifestFile.lastModified() > zipFile.lastModified()) { | |||
| return false; | |||
| } | |||
| return super.isUpToDate(scanners, zipFile); | |||
| return super.isUpToDate(scanners, fss, zipFile); | |||
| } | |||
| protected boolean createEmptyZip(File zipFile) { | |||
| @@ -585,6 +587,7 @@ public class Jar extends Zip { | |||
| manifest = null; | |||
| configuredManifest = savedConfiguredManifest; | |||
| filesetManifest = null; | |||
| originalManifest = null; | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * 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. | |||
| * | |||
| * 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.zip.CRC32; | |||
| import java.util.zip.ZipInputStream; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.FileScanner; | |||
| 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.FileSet; | |||
| 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.ZipScanner; | |||
| import org.apache.tools.ant.util.FileNameMapper; | |||
| 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.SourceFileScanner; | |||
| import org.apache.tools.ant.util.SourceSelector; | |||
| import org.apache.tools.zip.ZipEntry; | |||
| import org.apache.tools.zip.ZipOutputStream; | |||
| @@ -93,9 +100,11 @@ import org.apache.tools.zip.ZipOutputStream; | |||
| * | |||
| * @ant.task category="packaging" | |||
| */ | |||
| public class Zip extends MatchingTask { | |||
| public class Zip extends MatchingTask implements ResourceFactory { | |||
| protected File zipFile; | |||
| // use to scan own archive | |||
| private ZipScanner zs; | |||
| private File baseDir; | |||
| protected Hashtable entries = new Hashtable(); | |||
| private Vector groupfilesets = new Vector(); | |||
| @@ -117,6 +126,7 @@ public class Zip extends MatchingTask { | |||
| protected boolean doubleFilePass = false; | |||
| protected boolean skipWriting = false; | |||
| private FileUtils fileUtils; | |||
| /** | |||
| @@ -331,22 +341,28 @@ public class Zip extends MatchingTask { | |||
| // Create the scanners to pass to isUpToDate(). | |||
| Vector dss = new Vector(); | |||
| Vector vfss = new Vector(); | |||
| if (baseDir != null) { | |||
| dss.addElement(getDirectoryScanner(baseDir)); | |||
| FileSet fs = new FileSet(); | |||
| fs.setDir(baseDir); | |||
| vfss.addElement(fs); | |||
| } | |||
| for (int i = 0; i < filesets.size(); i++) { | |||
| FileSet fs = (FileSet) filesets.elementAt(i); | |||
| dss.addElement (fs.getDirectoryScanner(getProject())); | |||
| vfss.addElement(fs); | |||
| } | |||
| int dssSize = dss.size(); | |||
| FileScanner[] scanners = new FileScanner[dssSize]; | |||
| ResourceScanner[] scanners = new ResourceScanner[dssSize]; | |||
| dss.copyInto(scanners); | |||
| FileSet [] fss = new FileSet[dssSize]; | |||
| vfss.copyInto(fss); | |||
| boolean success = false; | |||
| try { | |||
| // quick exit if the target is up to date | |||
| // can also handle empty archives | |||
| if (isUpToDate(scanners, zipFile)) { | |||
| if (isUpToDate(scanners, fss, zipFile)) { | |||
| return; | |||
| } | |||
| @@ -642,6 +658,15 @@ public class Zip extends MatchingTask { | |||
| 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 | |||
| @@ -652,8 +677,17 @@ public class Zip extends MatchingTask { | |||
| * already); false if archive creation should proceed | |||
| * @exception BuildException if it likes | |||
| */ | |||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) | |||
| protected boolean isUpToDate(ResourceScanner[] scanners, | |||
| FileSet[] fss, File zipFile) | |||
| 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); | |||
| File[] files = grabFiles(scanners, fileNames); | |||
| if (files.length == 0) { | |||
| @@ -681,17 +715,39 @@ public class Zip extends MatchingTask { | |||
| return false; | |||
| } | |||
| SourceFileScanner sfs = new SourceFileScanner(this); | |||
| MergingMapper mm = new MergingMapper(); | |||
| mm.setTo(zipFile.getAbsolutePath()); | |||
| 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) { | |||
| @@ -723,6 +779,24 @@ public class Zip extends MatchingTask { | |||
| } | |||
| 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. | |||
| @@ -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 | |||
| * | |||
| * Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -55,18 +55,24 @@ | |||
| package org.apache.tools.ant.types; | |||
| 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.Project; | |||
| import org.apache.tools.ant.Task; | |||
| /** | |||
| * ZipScanner accesses the pattern matching algorithm in DirectoryScanner, | |||
| * which are protected methods that can only be accessed by subclassing. | |||
| * | |||
| * 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> | |||
| */ | |||
| public class ZipScanner extends DirectoryScanner { | |||
| @@ -75,35 +81,84 @@ public class ZipScanner extends DirectoryScanner { | |||
| * The zip file which should be scanned. | |||
| */ | |||
| 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 | |||
| */ | |||
| public void setSrc(File 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() { | |||
| 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() { | |||
| 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); | |||
| } | |||
| /** | |||
| * 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 | |||
| * | |||
| * Copyright (c) 2000-2002 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2000-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -58,6 +58,8 @@ import java.io.File; | |||
| import java.util.Vector; | |||
| import org.apache.tools.ant.Project; | |||
| 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; | |||
| /** | |||
| @@ -70,11 +72,12 @@ import org.apache.tools.ant.taskdefs.condition.Os; | |||
| * | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| */ | |||
| public class SourceFileScanner { | |||
| public class SourceFileScanner implements ResourceFactory { | |||
| protected Task task; | |||
| private FileUtils fileUtils; | |||
| private File destDir; // base directory of the fileset | |||
| /** | |||
| * @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, | |||
| 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(); | |||
| 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]); | |||
| 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; | |||
| } | |||
| @@ -179,4 +137,18 @@ public class SourceFileScanner { | |||
| } | |||
| 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.getHours() << 11) | |||
| | (time.getMinutes() << 5) | |||
| | (time.getSeconds() >> 1); | |||
| | ((time.getSeconds() + 2) >> 1); | |||
| byte[] result = new byte[4]; | |||
| result[0] = (byte) ((value & 0xFF)); | |||
| @@ -119,20 +119,20 @@ public class JarTest extends BuildFileTest { | |||
| jarModifiedDate, jarFile.lastModified()); | |||
| } | |||
| public void XtestRecreateWithoutUpdateAdditionalFiles() { | |||
| public void testRecreateWithoutUpdateAdditionalFiles() { | |||
| testRecreate("test4", "testRecreateWithoutUpdateAdditionalFiles"); | |||
| } | |||
| public void XtestRecreateWithUpdateAdditionalFiles() { | |||
| public void testRecreateWithUpdateAdditionalFiles() { | |||
| testRecreate("test4", "testRecreateWithUpdateAdditionalFiles"); | |||
| } | |||
| public void XtestRecreateWithoutUpdateNewerFile() { | |||
| public void testRecreateWithoutUpdateNewerFile() { | |||
| testRecreate("testRecreateNewerFileSetup", | |||
| "testRecreateWithoutUpdateNewerFile"); | |||
| } | |||
| public void XtestRecreateWithUpdateNewerFile() { | |||
| public void testRecreateWithUpdateNewerFile() { | |||
| testRecreate("testRecreateNewerFileSetup", | |||
| "testRecreateWithUpdateNewerFile"); | |||
| } | |||