diff --git a/src/main/org/apache/tools/ant/FileUtils.java b/src/main/org/apache/tools/ant/FileUtils.java new file mode 100644 index 000000000..66b2f2c27 --- /dev/null +++ b/src/main/org/apache/tools/ant/FileUtils.java @@ -0,0 +1,271 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 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; + +import java.io.*; +import java.util.*; + +import org.apache.tools.ant.types.FilterSet; + +/** + * Central representation of an Ant project. This class defines a + * Ant project with all of it's targets and tasks. It also provides + * the mechanism to kick off a build using a particular target name. + *

+ * This class also encapsulates methods which allow Files to be refered + * to using abstract path names which are translated to native system + * file paths at runtime as well as defining various project properties. + * + * @author duncan@x180.com + * @author Conor MacNeill + */ + +public class FileUtils { + private static Object lockReflection = new Object(); + private static java.lang.reflect.Method setLastModified = null; + + /** + * Convienence method to copy a file from a source to a destination. + * No filtering is performed. + * + * @throws IOException + */ + public static void copyFile(String sourceFile, String destFile) throws IOException { + copyFile(new File(sourceFile), new File(destFile), null, false, false); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used. + * + * @throws IOException + */ + public static void copyFile(String sourceFile, String destFile, FilterSet filterSet) + throws IOException + { + copyFile(new File(sourceFile), new File(destFile), filterSet, false, false); + } + + /** + * Convienence method to copy a file from a source to a + * destination specifying if token filtering must be used and if + * source files may overwrite newer destination files. + * + * @throws IOException + */ + public static void copyFile(String sourceFile, String destFile, FilterSet filterSet, + boolean overwrite) throws IOException { + copyFile(new File(sourceFile), new File(destFile), filterSet, + overwrite, false); + } + + /** + * Convienence method to copy a file from a source to a + * destination specifying if token filtering must be used, if + * source files may overwrite newer destination files and the + * last modified time of destFile file should be made equal + * to the last modified time of sourceFile. + * + * @throws IOException + */ + public static void copyFile(String sourceFile, String destFile, FilterSet filterSet, + boolean overwrite, boolean preserveLastModified) + throws IOException { + copyFile(new File(sourceFile), new File(destFile), filterSet, + overwrite, preserveLastModified); + } + + /** + * Convienence method to copy a file from a source to a destination. + * No filtering is performed. + * + * @throws IOException + */ + public static void copyFile(File sourceFile, File destFile) throws IOException { + copyFile(sourceFile, destFile, null, false, false); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used. + * + * @throws IOException + */ + public static void copyFile(File sourceFile, File destFile, FilterSet filterSet) + throws IOException { + copyFile(sourceFile, destFile, filterSet, false, false); + } + + /** + * Convienence method to copy a file from a source to a + * destination specifying if token filtering must be used and if + * source files may overwrite newer destination files. + * + * @throws IOException + */ + public static void copyFile(File sourceFile, File destFile, FilterSet filterSet, + boolean overwrite) throws IOException { + copyFile(sourceFile, destFile, filterSet, overwrite, false); + } + + /** + * Convienence method to copy a file from a source to a + * destination specifying if token filtering must be used, if + * source files may overwrite newer destination files and the + * last modified time of destFile file should be made equal + * to the last modified time of sourceFile. + * + * @throws IOException + */ + public static void copyFile(File sourceFile, File destFile, FilterSet filterSet, + boolean overwrite, boolean preserveLastModified) + throws IOException { + + if (overwrite || !destFile.exists() || + destFile.lastModified() < sourceFile.lastModified()) { + + if (destFile.exists() && destFile.isFile()) { + destFile.delete(); + } + + // ensure that parent dir of dest file exists! + // not using getParentFile method to stay 1.1 compat + File parent = new File(destFile.getParent()); + if (!parent.exists()) { + parent.mkdirs(); + } + + if (filterSet != null) { + BufferedReader in = new BufferedReader(new FileReader(sourceFile)); + BufferedWriter out = new BufferedWriter(new FileWriter(destFile)); + + int length; + String newline = null; + String line = in.readLine(); + while (line != null) { + if (line.length() == 0) { + out.newLine(); + } else { + newline = filterSet.replaceTokens(line); + out.write(newline); + out.newLine(); + } + line = in.readLine(); + } + + out.close(); + in.close(); + } else { + FileInputStream in = new FileInputStream(sourceFile); + FileOutputStream out = new FileOutputStream(destFile); + + byte[] buffer = new byte[8 * 1024]; + int count = 0; + do { + out.write(buffer, 0, count); + count = in.read(buffer, 0, buffer.length); + } while (count != -1); + + in.close(); + out.close(); + } + + if (preserveLastModified) { + setFileLastModified(destFile, sourceFile.lastModified()); + } + } + } + + /** + * Calls File.setLastModified(long time) in a Java 1.1 compatible way. + */ + public static void setFileLastModified(File file, long time) throws BuildException { + if (Project.getJavaVersion() == Project.JAVA_1_1) { + return; + } + if (setLastModified == null) { + synchronized (lockReflection) { + if (setLastModified == null) { + try { + setLastModified = + java.io.File.class.getMethod("setLastModified", + new Class[] {Long.TYPE}); + } catch (NoSuchMethodException nse) { + throw new BuildException("File.setlastModified not in JDK > 1.1?", + nse); + } + } + } + } + Long[] times = new Long[1]; + if (time < 0) { + times[0] = new Long(System.currentTimeMillis()); + } else { + times[0] = new Long(time); + } + try { + setLastModified.invoke(file, times); + } catch (java.lang.reflect.InvocationTargetException ite) { + Throwable nested = ite.getTargetException(); + throw new BuildException("Exception setting the modification time " + + "of " + file, nested); + } catch (Throwable other) { + throw new BuildException("Exception setting the modification time " + + "of " + file, other); + } + } + +} + diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index 1039738e6..88ba00e9a 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -58,6 +58,8 @@ import java.io.*; import java.util.*; import java.text.*; +import org.apache.tools.ant.types.FilterSet; + /** * Central representation of an Ant project. This class defines a * Ant project with all of it's targets and tasks. It also provides @@ -91,8 +93,8 @@ public class Project { public static final String JAVA_1_3 = "1.3"; public static final String JAVA_1_4 = "1.4"; - public static final String TOKEN_START = "@"; - public static final String TOKEN_END = "@"; + public static final String TOKEN_START = FilterSet.DEFAULT_TOKEN_START; + public static final String TOKEN_END = FilterSet.DEFAULT_TOKEN_END; private String name; @@ -103,14 +105,11 @@ public class Project { private Hashtable dataClassDefinitions = new Hashtable(); private Hashtable taskClassDefinitions = new Hashtable(); private Hashtable targets = new Hashtable(); - private Hashtable filters = new Hashtable(); + private FilterSet globalFilterSet = new FilterSet(); private File baseDir; private Vector listeners = new Vector(); - private static java.lang.reflect.Method setLastModified = null; - private static Object lockReflection = new Object(); - /** The system classloader - may be null */ private ClassLoader systemLoader = null; @@ -254,6 +253,12 @@ public class Project { fireMessageLogged(target, msg, msgLevel); } + + public FilterSet getGlobalFilterSet() { + return globalFilterSet; + } + + public void setProperty(String name, String value) { // command line properties take precedence if (null != userProperties.get(name)) { @@ -315,15 +320,19 @@ public class Project { return name; } + /** @deprecated */ public void addFilter(String token, String value) { - if (token == null) return; - log("Setting token to filter: " + token + " -> " - + value, MSG_DEBUG); - this.filters.put(token, value); + if (token == null) { + return; + } + + globalFilterSet.addFilter(new FilterSet.Filter(token, value)); } + /** @deprecated */ public Hashtable getFilters() { - return filters; + // we need to build the hashtable dynamically + return globalFilterSet.getFilterHash(); } // match basedir attribute in xml @@ -505,6 +514,9 @@ public class Project { } else { o = ctor.newInstance(new Object[] {this}); } + if (o instanceof ProjectComponent) { + ((ProjectComponent)o).setProject(this); + } String msg = " +DataType: " + typeName; log (msg, MSG_DEBUG); return o; @@ -674,9 +686,11 @@ public class Project { * No filtering is performed. * * @throws IOException + * + * @deprecated */ public void copyFile(String sourceFile, String destFile) throws IOException { - copyFile(new File(sourceFile), new File(destFile), false); + FileUtils.copyFile(sourceFile, destFile); } /** @@ -686,9 +700,8 @@ public class Project { * @throws IOException */ public void copyFile(String sourceFile, String destFile, boolean filtering) - throws IOException - { - copyFile(new File(sourceFile), new File(destFile), filtering); + throws IOException { + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null); } /** @@ -700,8 +713,7 @@ public class Project { */ public void copyFile(String sourceFile, String destFile, boolean filtering, boolean overwrite) throws IOException { - copyFile(new File(sourceFile), new File(destFile), filtering, - overwrite); + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null, overwrite); } /** @@ -716,8 +728,8 @@ public class Project { public void copyFile(String sourceFile, String destFile, boolean filtering, boolean overwrite, boolean preserveLastModified) throws IOException { - copyFile(new File(sourceFile), new File(destFile), filtering, - overwrite, preserveLastModified); + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null, + overwrite, preserveLastModified); } /** @@ -727,7 +739,7 @@ public class Project { * @throws IOException */ public void copyFile(File sourceFile, File destFile) throws IOException { - copyFile(sourceFile, destFile, false); + FileUtils.copyFile(sourceFile, destFile); } /** @@ -738,7 +750,7 @@ public class Project { */ public void copyFile(File sourceFile, File destFile, boolean filtering) throws IOException { - copyFile(sourceFile, destFile, filtering, false); + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null); } /** @@ -750,7 +762,7 @@ public class Project { */ public void copyFile(File sourceFile, File destFile, boolean filtering, boolean overwrite) throws IOException { - copyFile(sourceFile, destFile, filtering, overwrite, false); + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null, overwrite); } /** @@ -765,63 +777,8 @@ public class Project { public void copyFile(File sourceFile, File destFile, boolean filtering, boolean overwrite, boolean preserveLastModified) throws IOException { - - if (overwrite || !destFile.exists() || - destFile.lastModified() < sourceFile.lastModified()) { - - if (destFile.exists() && destFile.isFile()) { - destFile.delete(); - } - - log("Copy: " + sourceFile.getAbsolutePath() + " -> " - + destFile.getAbsolutePath(), MSG_VERBOSE); - - // ensure that parent dir of dest file exists! - // not using getParentFile method to stay 1.1 compat - File parent = new File(destFile.getParent()); - if (!parent.exists()) { - parent.mkdirs(); - } - - if (filtering) { - BufferedReader in = new BufferedReader(new FileReader(sourceFile)); - BufferedWriter out = new BufferedWriter(new FileWriter(destFile)); - - int length; - String newline = null; - String line = in.readLine(); - while (line != null) { - if (line.length() == 0) { - out.newLine(); - } else { - newline = replace(line, filters); - out.write(newline); - out.newLine(); - } - line = in.readLine(); - } - - out.close(); - in.close(); - } else { - FileInputStream in = new FileInputStream(sourceFile); - FileOutputStream out = new FileOutputStream(destFile); - - byte[] buffer = new byte[8 * 1024]; - int count = 0; - do { - out.write(buffer, 0, count); - count = in.read(buffer, 0, buffer.length); - } while (count != -1); - - in.close(); - out.close(); - } - - if (preserveLastModified) { - setFileLastModified(destFile, sourceFile.lastModified()); - } - } + FileUtils.copyFile(sourceFile, destFile, filtering ? globalFilterSet : null, + overwrite, preserveLastModified); } /** @@ -833,82 +790,8 @@ public class Project { + " in JDK 1.1", Project.MSG_WARN); return; } - if (setLastModified == null) { - synchronized (lockReflection) { - if (setLastModified == null) { - try { - setLastModified = - java.io.File.class.getMethod("setLastModified", - new Class[] {Long.TYPE}); - } catch (NoSuchMethodException nse) { - throw new BuildException("File.setlastModified not in JDK > 1.1?", - nse); - } - } - } - } - Long[] times = new Long[1]; - if (time < 0) { - times[0] = new Long(System.currentTimeMillis()); - } else { - times[0] = new Long(time); - } - try { - log("Setting modification time for " + file, MSG_VERBOSE); - setLastModified.invoke(file, times); - } catch (java.lang.reflect.InvocationTargetException ite) { - Throwable nested = ite.getTargetException(); - throw new BuildException("Exception setting the modification time " - + "of " + file, nested); - } catch (Throwable other) { - throw new BuildException("Exception setting the modification time " - + "of " + file, other); - } - } - - /** - * Does replacement on the given string using the given token table. - * - * @returns the string with the token replaced. - */ - private String replace(String s, Hashtable tokens) { - int index = s.indexOf(TOKEN_START); - - if (index > -1) { - try { - StringBuffer b = new StringBuffer(); - int i = 0; - String token = null; - String value = null; - - do { - int endIndex = s.indexOf(TOKEN_END, - index + TOKEN_START.length() + 1); - if (endIndex == -1) { - break; - } - token = s.substring(index + TOKEN_START.length(), endIndex); - b.append(s.substring(i, index)); - if (tokens.containsKey(token)) { - value = (String) tokens.get(token); - log("Replacing: " + TOKEN_START + token + TOKEN_END + " -> " + value, MSG_VERBOSE); - b.append(value); - i = index + TOKEN_START.length() + token.length() + TOKEN_END.length(); - } else { - // just append TOKEN_START and search further - b.append(TOKEN_START); - i = index + TOKEN_START.length(); - } - } while ((index = s.indexOf(TOKEN_START, i)) > -1); - - b.append(s.substring(i)); - return b.toString(); - } catch (StringIndexOutOfBoundsException e) { - return s; - } - } else { - return s; - } + FileUtils.setFileLastModified(file, time); + log("Setting modification time for " + file, MSG_VERBOSE); } /** diff --git a/src/main/org/apache/tools/ant/taskdefs/Copy.java b/src/main/org/apache/tools/ant/taskdefs/Copy.java index 673ccd00a..1ea6a6e9e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Copy.java +++ b/src/main/org/apache/tools/ant/taskdefs/Copy.java @@ -73,6 +73,7 @@ import java.util.*; * * @author Glenn McAllister glennm@ca.ibm.com * @author Stefan Bodewig + * @author Michael McCallum */ public class Copy extends Task { protected File file = null; // the source file @@ -91,7 +92,8 @@ public class Copy extends Task { protected Hashtable dirCopyMap = new Hashtable(); protected Mapper mapperElement = null; - + private Vector filterSets = new Vector(); + /** * Sets a single source file to copy. */ @@ -113,6 +115,15 @@ public class Copy extends Task { this.destDir = destDir; } + /** + * Create a nested filterset + */ + public FilterSet createFilterSet() { + FilterSet filterSet = new FilterSet(); + filterSets.addElement(filterSet); + return filterSet; + } + /** * Give the copied files the same last modified time as the original files. */ @@ -120,6 +131,15 @@ public class Copy extends Task { preserveLastModified = Project.toBoolean(preserve); } + /** + * Get the filtersets being applied to this operation. + * + * @return a vector of FilterSet objects + */ + protected Vector getFilterSets() { + return filterSets; + } + /** * Sets filtering. */ @@ -338,11 +358,15 @@ public class Copy extends Task { try { log("Copying " + fromFile + " to " + toFile, verbosity); - project.copyFile(fromFile, - toFile, - filtering, - forceOverwrite, - preserveLastModified); + FilterSet executionFilterSet = new FilterSet(); + if (filtering) { + executionFilterSet.addFilterSet(project.getGlobalFilterSet()); + } + for (Enumeration filterEnum = filterSets.elements(); filterEnum.hasMoreElements();) { + executionFilterSet.addFilterSet((FilterSet)filterEnum.nextElement()); + } + FileUtils.copyFile(fromFile, toFile, executionFilterSet, + forceOverwrite, preserveLastModified); } catch (IOException ioe) { String msg = "Failed to copy " + fromFile + " to " + toFile + " due to " + ioe.getMessage(); diff --git a/src/main/org/apache/tools/ant/taskdefs/Move.java b/src/main/org/apache/tools/ant/taskdefs/Move.java index 30504618f..ec3715580 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Move.java +++ b/src/main/org/apache/tools/ant/taskdefs/Move.java @@ -100,7 +100,17 @@ public class Move extends Copy { try { log("Moving " + fromFile + " to " + toFile, verbosity); - project.copyFile(fromFile, toFile, filtering, forceOverwrite); + + FilterSet executionFilterSet = new FilterSet(); + if (filtering) { + executionFilterSet.addFilterSet(project.getGlobalFilterSet()); + } + for (Enumeration filterEnum = getFilterSets().elements(); filterEnum.hasMoreElements();) { + executionFilterSet.addFilterSet((FilterSet)filterEnum.nextElement()); + } + FileUtils.copyFile(fromFile, toFile, executionFilterSet, + forceOverwrite); + File f = new File(fromFile); if (!f.delete()) { throw new BuildException("Unable to delete file " + f.getAbsolutePath()); diff --git a/src/main/org/apache/tools/ant/types/FilterSet.java b/src/main/org/apache/tools/ant/types/FilterSet.java new file mode 100644 index 000000000..67ff8d8c0 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/FilterSet.java @@ -0,0 +1,417 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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; + +// java io classes +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +// java util classes +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; +import java.util.Vector; + +// ant classes +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + * A set of filters to be applied to something. + * + * A filter set may have starttoken and endtokens defined. + * + * @author Michael McCallum + * @created 14 March 2001 + */ +public class FilterSet extends DataType { + + /** + * Individual filter component of filterset + * + * @author Michael McCallum + * @created 14 March 2001 + */ + public static class Filter { + /** Token which will be replaced in the filter operation */ + String token; + + /** The value which will replace the token in the filtering operation */ + String value; + + /** + * Constructor for the Filter object + * + * @param token The token which will be replaced when filtering + * @param value The value which will replace the token when filtering + */ + public Filter(String token, String value) { + this.token = token; + this.value = value; + } + + /** + * No argument conmstructor + */ + public Filter() { + } + + /** + * Sets the Token attribute of the Filter object + * + * @param token The new Token value + */ + public void setToken( String token ) { + this.token = token; + } + + /** + * Sets the Value attribute of the Filter object + * + * @param value The new Value value + */ + public void setValue( String value ) { + this.value = value; + } + + /** + * Gets the Token attribute of the Filter object + * + * @return The Token value + */ + public String getToken() { + return token; + } + + /** + * Gets the Value attribute of the Filter object + * + * @return The Value value + */ + public String getValue() { + return value; + } + } + + /** + * The filtersfile nested element. + * + * @author Michael McCallum + * @created Thursday, April 19, 2001 + */ + public class FiltersFile { + + /** + * Constructor for the Filter object + */ + public FiltersFile() { + } + + /** + * Sets the file from which filters will be read. + * + * @param file the file from which filters will be read. + */ + public void setFile(File file) { + readFiltersFromFile(file); + } + } + + /** The default token start string */ + public static final String DEFAULT_TOKEN_START = "@"; + + /** The default token end string */ + public static final String DEFAULT_TOKEN_END = "@"; + + private String startOftoken = DEFAULT_TOKEN_START; + private String endOftoken = DEFAULT_TOKEN_END; + + /** + * List of ordered filters and filter files. + */ + private Vector filters = new Vector(); + + public FilterSet() { + } + + /** + * Create a Filterset from another filterset + * + * @param filterset the filterset upon which this filterset will be based. + */ + protected FilterSet(FilterSet filterset) { + super(); + this.filters = (Vector)filterset.getFilters().clone(); + } + + protected Vector getFilters() { + if (isReference()) { + return getRef().getFilters(); + } + return filters; + } + + protected FilterSet getRef() { + return (FilterSet)getCheckedRef(FilterSet.class, "filterset"); + } + + /** + * Gets the filter hash of the FilterSet. + * + * @return The hash of the tokens and values for quick lookup. + */ + public Hashtable getFilterHash() { + int filterSize = getFilters().size(); + Hashtable filterHash = new Hashtable(filterSize); + for (Enumeration e = getFilters().elements(); e.hasMoreElements();) { + Filter filter = (Filter) e.nextElement(); + filterHash.put(filter.getToken(), filter.getValue()); + } + return filterHash; + } + + /** + * set the file containing the filters for this filterset. + * + * @param filtersFile sets the filter fil to read filters for this filter set from. + * @exception BuildException if there is a problem reading the filters + */ + public void setFiltersfile(File filtersFile) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + readFiltersFromFile(filtersFile); + } + + /** + * The string used to id the beginning of a token. + * + * @param startOfToken The new Begintoken value + */ + public void setBeginToken(String startOfToken) { + if (isReference()) { + throw tooManyAttributes(); + } + startOftoken = startOfToken; + } + + /** + * The string used to id the end of a token. + * + * @param endOfToken The new Endtoken value + */ + public void setEndToken( String endOfToken ) { + if (isReference()) { + throw tooManyAttributes(); + } + endOftoken = endOfToken; + } + + /** + * Read the filters from the given file. + * + * @param filtersFile the file from which filters are read + * @exception BuildException Throw a build exception when unable to read the + * file. + */ + public void readFiltersFromFile(File filtersFile) throws BuildException { + if (filtersFile.isFile()) { + log("Reading filters from " + filtersFile, Project.MSG_VERBOSE ); + FileInputStream in = null; + try { + Properties props = new Properties(); + in = new FileInputStream(filtersFile); + props.load(in); + + Enumeration enum = props.propertyNames(); + Vector filters = getFilters(); + while (enum.hasMoreElements()) { + String strPropName = (String) enum.nextElement(); + String strValue = props.getProperty(strPropName); + filters.addElement(new Filter(strPropName, strValue)); + } + } + catch (Exception e) { + throw new BuildException( "Could not read filters from file: " + filtersFile ); + } + finally { + if ( in != null ) { + try { + in.close(); + } + catch (IOException ioex) { + } + } + } + } + else { + throw new BuildException( "Must specify a file not a directory in the filtersfile attribute:" + filtersFile ); + } + } + + /** + * Does replacement on the given string with token matching. + * This uses the defined starttoken and endtoken values which default to @ for both. + * + * @param line The line to process the tokens in. + * @return The string with the tokens replaced. + */ + public String replaceTokens(String line) { + int index = line.indexOf(startOftoken); + + if (index > -1) { + Hashtable tokens = getFilterHash(); + try { + StringBuffer b = new StringBuffer(); + int i = 0; + String token = null; + String value = null; + + do { + int endIndex = line.indexOf(endOftoken, index + startOftoken.length() + 1 ); + if (endIndex == -1) { + break; + } + token = line.substring(index + startOftoken.length(), endIndex ); + b.append(line.substring(i, index)); + if (tokens.containsKey(token)) { + value = (String)tokens.get(token); + log( "Replacing: " + startOftoken + token + endOftoken + " -> " + value, Project.MSG_VERBOSE ); + b.append(value); + i = index + startOftoken.length() + token.length() + endOftoken.length(); + } + else { + // just append startOftoken and search further + b.append(startOftoken); + i = index + startOftoken.length(); + } + } while ((index = line.indexOf( startOftoken, i )) > -1 ); + + b.append(line.substring(i)); + return b.toString(); + } + catch (StringIndexOutOfBoundsException e) { + return line; + } + } + else { + return line; + } + } + + /** + * Create a new filter + * + * @param the filter to be added + */ + public void addFilter(Filter filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + filters.addElement(filter); + } + + /** + * Create a new FiltersFile + * + * @return The filter that was created. + */ + public FiltersFile createFiltersfile() { + if (isReference()) { + throw noChildrenAllowed(); + } + return new FiltersFile(); + } + + /** + * Add a new filter made from the given token and value. + * + * @param token The token for the new filter. + * @param value The value for the new filter. + */ + public void addFilter(String token, String value) { + if (isReference()) { + throw noChildrenAllowed(); + } + filters.addElement(new Filter(token, value)); + } + + /** + * Add a Filterset to this filter set + * + * @param filterSet the filterset to be added to this filterset + */ + public void addFilterSet(FilterSet filterSet) { + if (isReference()) { + throw noChildrenAllowed(); + } + for (Enumeration e = filterSet.getFilters().elements(); e.hasMoreElements();) { + filters.addElement((Filter)e.nextElement()); + } + } + + /** + * Test to see if this filter set it empty. + * + * @return Return true if there are filter in this set otherwise false. + */ + public boolean hasFilters() { + return getFilters().size() > 0; + } +} + + + diff --git a/src/main/org/apache/tools/ant/types/defaults.properties b/src/main/org/apache/tools/ant/types/defaults.properties index fe104861f..c83c82102 100644 --- a/src/main/org/apache/tools/ant/types/defaults.properties +++ b/src/main/org/apache/tools/ant/types/defaults.properties @@ -2,3 +2,5 @@ path=org.apache.tools.ant.types.Path fileset=org.apache.tools.ant.types.FileSet patternset=org.apache.tools.ant.types.PatternSet mapper=org.apache.tools.ant.types.Mapper +filterset=org.apache.tools.ant.types.FilterSet +