From 9d74327d0aa7052193a0fcd9430f6f8f3509e619 Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Sat, 18 Jan 2003 06:51:21 +0000 Subject: [PATCH] refactoring of the Selector and a new subclass , which has a more advanced definition of different from just timestamps. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273826 13f79535-47bb-0310-9956-ffa450edef68 --- .../selectors/BaseSelectorContainer.java | 7 + .../ant/types/selectors/DependSelector.java | 94 +--------- .../types/selectors/DifferentSelector.java | 130 +++++++++++++ .../ant/types/selectors/MappingSelector.java | 172 ++++++++++++++++++ 4 files changed, 318 insertions(+), 85 deletions(-) create mode 100644 src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java create mode 100644 src/main/org/apache/tools/ant/types/selectors/MappingSelector.java diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java index 916f2dd30..7d8ebee2d 100644 --- a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java +++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java @@ -284,5 +284,12 @@ public abstract class BaseSelectorContainer extends BaseSelector appendSelector(selector); } + /** + * adds a different selector to the selector list + */ + public void addDifferent(DifferentSelector selector) { + appendSelector(selector); + } + } diff --git a/src/main/org/apache/tools/ant/types/selectors/DependSelector.java b/src/main/org/apache/tools/ant/types/selectors/DependSelector.java index 37799c629..8d2aecd8d 100644 --- a/src/main/org/apache/tools/ant/types/selectors/DependSelector.java +++ b/src/main/org/apache/tools/ant/types/selectors/DependSelector.java @@ -70,17 +70,10 @@ import org.apache.tools.ant.util.IdentityMapper; * @author Bruce Atherton * @since 1.5 */ -public class DependSelector extends BaseSelector { - - private File targetdir = null; - private Mapper mapperElement = null; - private FileNameMapper map = null; - private int granularity = 0; +public class DependSelector extends MappingSelector { public DependSelector() { - if (Os.isFamily("dos")) { - granularity = 2000; - } + } public String toString() { @@ -105,85 +98,16 @@ public class DependSelector extends BaseSelector { return buf.toString(); } - /** - * The name of the file or directory which is checked for out-of-date - * files. - * - * @param targetdir the directory to scan looking for files. - */ - public void setTargetdir(File targetdir) { - this.targetdir = targetdir; - } - - /** - * Sets the number of milliseconds leeway we will give before we consider - * a file out of date. - */ - public void setGranularity(int granularity) { - this.granularity = granularity; - } - - /** - * Defines the FileNameMapper to use (nested mapper element). - */ - public Mapper createMapper() throws BuildException { - if (mapperElement != null) { - throw new BuildException("Cannot define more than one mapper"); - } - mapperElement = new Mapper(getProject()); - return mapperElement; - } - /** - * Checks to make sure all settings are kosher. In this case, it - * means that the dest attribute has been set and we have a mapper. + * this test is our selection test that compared the file with the destfile + * @param srcfile + * @param destfile + * @return */ - public void verifySettings() { - if (targetdir == null) { - setError("The targetdir attribute is required."); - } - if (mapperElement == null) { - map = new IdentityMapper(); - } - else { - map = mapperElement.getImplementation(); - } - if (map == null) { - setError("Could not set element."); - } - } - - /** - * The heart of the matter. This is where the selector gets to decide - * on the inclusion of a file in a particular fileset. - * - * @param basedir the base directory the scan is being done from - * @param filename is the name of the file to check - * @param file is a java.io.File object the selector can use - * @return whether the file should be selected or not - */ - public boolean isSelected(File basedir, String filename, File file) { - - // throw BuildException on error - validate(); - - // Determine file whose out-of-dateness is to be checked - String[] destfiles = map.mapFileName(filename); - // If filename does not match the To attribute of the mapper - // then filter it out of the files we are considering - if (destfiles == null) { - return false; - } - // Sanity check - if (destfiles.length != 1 || destfiles[0] == null) { - throw new BuildException("Invalid destination file results for " - + targetdir.getName() + " with filename " + filename); - } - String destname = destfiles[0]; - File destfile = new File(targetdir,destname); - - return SelectorUtils.isOutOfDate(file, destfile, granularity); + public boolean selectionTest(File srcfile, File destfile) { + boolean selected=SelectorUtils.isOutOfDate(srcfile, destfile, granularity); + return selected; } } diff --git a/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java b/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java new file mode 100644 index 000000000..9e6c0d6a8 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java @@ -0,0 +1,130 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 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 + * . + */ + +package org.apache.tools.ant.types.selectors; + +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.BuildException; + +import java.io.File; +import java.io.IOException; + +/** + * This selector selects files against a mapped set of target files, selecting all those + * files which are different. A byte-by-byte comparision is performed on equal length files; + * files with different lengths are deemed different automatically; files with identical timestamps + * are viewed as matching by default, unless you specify otherwise. + *

+ * This is a useful selector to work with programs and tasks that don't handle + * dependency checking properly; Even if a predecessor task always creates its + * output files, followup tasks can be driven off copies made with a different selector, + * so their dependencies are driven on the absolute state of the files, not a timestamp. + *

+ * Clearly, however, bulk file comparisons is inefficient; anything that can use + * timestamps is to be preferred. If this selector must be used, use it over as few files + * as possible, perhaps following it with an <uptodate;> to keep the descendent + * routines conditional. + * + */ +public class DifferentSelector extends MappingSelector { + + private FileUtils fileUtils= FileUtils.newFileUtils(); + + private boolean ignoreFileTimes=false; + + + /** + * This flag tells the selector to ignore file times in the comparison + * @param ignoreFileTimes + */ + public void setIgnoreFileTimes(boolean ignoreFileTimes) { + this.ignoreFileTimes = ignoreFileTimes; + } + + /** + * this test is our selection test that compared the file with the destfile + * @param srcfile + * @param destfile + * @return + */ + protected boolean selectionTest(File srcfile, File destfile) { + + //if either of them is missing, they are different + if (srcfile.exists() != destfile.exists()) { + return true; + } + + if (srcfile.length() != destfile.length()) { + // different size =>different files + return true; + } + + //same date if dest timestamp is within granularity of the srcfile + boolean sameDate; + sameDate = destfile.lastModified() >= srcfile.lastModified() - granularity + && destfile.lastModified() <= srcfile.lastModified() + granularity; + + //and when ignoreFileTimes is set we claim the files are now equal + if(sameDate && !ignoreFileTimes) { + return true; + } + + //here do a bulk comparison + try { + return !fileUtils.contentEquals(srcfile,destfile); + } catch (IOException e) { + throw new BuildException("while comparing "+srcfile+" and "+destfile,e); + } + } +} diff --git a/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java b/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java new file mode 100644 index 000000000..83131b4d8 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java @@ -0,0 +1,172 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 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 + * . + */ + +package org.apache.tools.ant.types.selectors; + +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.condition.Os; +import org.apache.tools.ant.util.IdentityMapper; +import org.apache.tools.ant.util.FileNameMapper; + +import java.io.File; + +/** + * A mapping selector is an abstract class adding mapping support to the base + * selector + */ +public abstract class MappingSelector extends BaseSelector { + protected File targetdir = null; + protected Mapper mapperElement = null; + protected FileNameMapper map = null; + protected int granularity = 0; + + public MappingSelector() { + if (Os.isFamily("dos")) { + granularity = 2000; + } + } + + + /** + * The name of the file or directory which is checked for out-of-date + * files. + * + * @param targetdir the directory to scan looking for files. + */ + public void setTargetdir(File targetdir) { + this.targetdir = targetdir; + } + + /** + * Defines the FileNameMapper to use (nested mapper element). + */ + public Mapper createMapper() throws BuildException { + if (mapperElement != null) { + throw new BuildException("Cannot define more than one mapper"); + } + mapperElement = new Mapper(getProject()); + return mapperElement; + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the dest attribute has been set and we have a mapper. + */ + public void verifySettings() { + if (targetdir == null) { + setError("The targetdir attribute is required."); + } + if (mapperElement == null) { + map = new IdentityMapper(); + } + else { + map = mapperElement.getImplementation(); + } + if (map == null) { + setError("Could not set element."); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a java.io.File object the selector can use + * @return whether the file should be selected or not + */ + public boolean isSelected(File basedir, String filename, File file) { + + // throw BuildException on error + validate(); + + // Determine file whose out-of-dateness is to be checked + String[] destfiles = map.mapFileName(filename); + // If filename does not match the To attribute of the mapper + // then filter it out of the files we are considering + if (destfiles == null) { + return false; + } + // Sanity check + if (destfiles.length != 1 || destfiles[0] == null) { + throw new BuildException("Invalid destination file results for " + + targetdir.getName() + " with filename " + filename); + } + String destname = destfiles[0]; + File destfile = new File(targetdir,destname); + + boolean selected = selectionTest(file, destfile); + return selected; + } + + /** + * this test is our selection test that compared the file with the destfile + * @param srcfile file to test; may be null + * @param destfile destination file + * @return + */ + protected abstract boolean selectionTest(File srcfile, File destfile); + + /** + * Sets the number of milliseconds leeway we will give before we consider + * a file out of date. Defaults to 2000 on MS-DOS derivatives as the FAT file + * system. + */ + public void setGranularity(int granularity) { + this.granularity = granularity; + } + +}