patch from PR1545. There is also more to come. PR: 1545 Submitted by: Michael McCallum <gholam@xtra.co.nz> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269459 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| 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. | |||
| * <p> | |||
| * 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 <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
| */ | |||
| 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 <code>destFile</code> file should be made equal | |||
| * to the last modified time of <code>sourceFile</code>. | |||
| * | |||
| * @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 <code>destFile</code> file should be made equal | |||
| * to the last modified time of <code>sourceFile</code>. | |||
| * | |||
| * @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); | |||
| } | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| /** | |||
| @@ -73,6 +73,7 @@ import java.util.*; | |||
| * | |||
| * @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <A href="gholam@xtra.co.nz">Michael McCallum</A> | |||
| */ | |||
| 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(); | |||
| @@ -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()); | |||
| @@ -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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| 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 <A href="mailto:gholam@xtra.co.nz"> Michael McCallum </A> | |||
| * @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; | |||
| } | |||
| } | |||
| @@ -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 | |||