Browse Source

Initial fix for the <jar> doesn't update bug, will need some

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-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
a9353331a9
12 changed files with 935 additions and 103 deletions
  1. +3
    -0
      WHATSNEW
  2. +83
    -1
      src/main/org/apache/tools/ant/DirectoryScanner.java
  3. +85
    -0
      src/main/org/apache/tools/ant/ResourceScanner.java
  4. +6
    -3
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  5. +88
    -14
      src/main/org/apache/tools/ant/taskdefs/Zip.java
  6. +165
    -0
      src/main/org/apache/tools/ant/types/Resource.java
  7. +73
    -0
      src/main/org/apache/tools/ant/types/ResourceFactory.java
  8. +232
    -17
      src/main/org/apache/tools/ant/types/ZipScanner.java
  9. +35
    -63
      src/main/org/apache/tools/ant/util/SourceFileScanner.java
  10. +160
    -0
      src/main/org/apache/tools/ant/util/SourceSelector.java
  11. +1
    -1
      src/main/org/apache/tools/zip/ZipOutputStream.java
  12. +4
    -4
      src/testcases/org/apache/tools/ant/taskdefs/JarTest.java

+ 3
- 0
WHATSNEW View File

@@ -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.


+ 83
- 1
src/main/org/apache/tools/ant/DirectoryScanner.java View File

@@ -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());
}

}

+ 85
- 0
src/main/org/apache/tools/ant/ResourceScanner.java View File

@@ -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();
}

+ 6
- 3
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -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;
}
}



+ 88
- 14
src/main/org/apache/tools/ant/taskdefs/Zip.java View File

@@ -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.


+ 165
- 0
src/main/org/apache/tools/ant/types/Resource.java View File

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

}

+ 73
- 0
src/main/org/apache/tools/ant/types/ResourceFactory.java View File

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

+ 232
- 17
src/main/org/apache/tools/ant/types/ZipScanner.java View File

@@ -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;
}
}

+ 35
- 63
src/main/org/apache/tools/ant/util/SourceFileScanner.java View File

@@ -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());
}
}


+ 160
- 0
src/main/org/apache/tools/ant/util/SourceSelector.java View File

@@ -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;
}
}

+ 1
- 1
src/main/org/apache/tools/zip/ZipOutputStream.java View File

@@ -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));


+ 4
- 4
src/testcases/org/apache/tools/ant/taskdefs/JarTest.java View File

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


Loading…
Cancel
Save