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