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.util.*; | ||||
import java.text.*; | import java.text.*; | ||||
import org.apache.tools.ant.types.FilterSet; | |||||
/** | /** | ||||
* Central representation of an Ant project. This class defines a | * Central representation of an Ant project. This class defines a | ||||
* Ant project with all of it's targets and tasks. It also provides | * 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_3 = "1.3"; | ||||
public static final String JAVA_1_4 = "1.4"; | 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; | private String name; | ||||
@@ -103,14 +105,11 @@ public class Project { | |||||
private Hashtable dataClassDefinitions = new Hashtable(); | private Hashtable dataClassDefinitions = new Hashtable(); | ||||
private Hashtable taskClassDefinitions = new Hashtable(); | private Hashtable taskClassDefinitions = new Hashtable(); | ||||
private Hashtable targets = new Hashtable(); | private Hashtable targets = new Hashtable(); | ||||
private Hashtable filters = new Hashtable(); | |||||
private FilterSet globalFilterSet = new FilterSet(); | |||||
private File baseDir; | private File baseDir; | ||||
private Vector listeners = new Vector(); | 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 */ | /** The system classloader - may be null */ | ||||
private ClassLoader systemLoader = null; | private ClassLoader systemLoader = null; | ||||
@@ -254,6 +253,12 @@ public class Project { | |||||
fireMessageLogged(target, msg, msgLevel); | fireMessageLogged(target, msg, msgLevel); | ||||
} | } | ||||
public FilterSet getGlobalFilterSet() { | |||||
return globalFilterSet; | |||||
} | |||||
public void setProperty(String name, String value) { | public void setProperty(String name, String value) { | ||||
// command line properties take precedence | // command line properties take precedence | ||||
if (null != userProperties.get(name)) { | if (null != userProperties.get(name)) { | ||||
@@ -315,15 +320,19 @@ public class Project { | |||||
return name; | return name; | ||||
} | } | ||||
/** @deprecated */ | |||||
public void addFilter(String token, String value) { | 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() { | public Hashtable getFilters() { | ||||
return filters; | |||||
// we need to build the hashtable dynamically | |||||
return globalFilterSet.getFilterHash(); | |||||
} | } | ||||
// match basedir attribute in xml | // match basedir attribute in xml | ||||
@@ -505,6 +514,9 @@ public class Project { | |||||
} else { | } else { | ||||
o = ctor.newInstance(new Object[] {this}); | o = ctor.newInstance(new Object[] {this}); | ||||
} | } | ||||
if (o instanceof ProjectComponent) { | |||||
((ProjectComponent)o).setProject(this); | |||||
} | |||||
String msg = " +DataType: " + typeName; | String msg = " +DataType: " + typeName; | ||||
log (msg, MSG_DEBUG); | log (msg, MSG_DEBUG); | ||||
return o; | return o; | ||||
@@ -674,9 +686,11 @@ public class Project { | |||||
* No filtering is performed. | * No filtering is performed. | ||||
* | * | ||||
* @throws IOException | * @throws IOException | ||||
* | |||||
* @deprecated | |||||
*/ | */ | ||||
public void copyFile(String sourceFile, String destFile) throws IOException { | 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 | * @throws IOException | ||||
*/ | */ | ||||
public void copyFile(String sourceFile, String destFile, boolean filtering) | 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, | public void copyFile(String sourceFile, String destFile, boolean filtering, | ||||
boolean overwrite) throws IOException { | 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, | public void copyFile(String sourceFile, String destFile, boolean filtering, | ||||
boolean overwrite, boolean preserveLastModified) | boolean overwrite, boolean preserveLastModified) | ||||
throws IOException { | 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 | * @throws IOException | ||||
*/ | */ | ||||
public void copyFile(File sourceFile, File destFile) 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) | public void copyFile(File sourceFile, File destFile, boolean filtering) | ||||
throws IOException { | 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, | public void copyFile(File sourceFile, File destFile, boolean filtering, | ||||
boolean overwrite) throws IOException { | 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, | public void copyFile(File sourceFile, File destFile, boolean filtering, | ||||
boolean overwrite, boolean preserveLastModified) | boolean overwrite, boolean preserveLastModified) | ||||
throws IOException { | 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); | + " in JDK 1.1", Project.MSG_WARN); | ||||
return; | 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 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="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | ||||
* @author <A href="gholam@xtra.co.nz">Michael McCallum</A> | |||||
*/ | */ | ||||
public class Copy extends Task { | public class Copy extends Task { | ||||
protected File file = null; // the source file | protected File file = null; // the source file | ||||
@@ -91,7 +92,8 @@ public class Copy extends Task { | |||||
protected Hashtable dirCopyMap = new Hashtable(); | protected Hashtable dirCopyMap = new Hashtable(); | ||||
protected Mapper mapperElement = null; | protected Mapper mapperElement = null; | ||||
private Vector filterSets = new Vector(); | |||||
/** | /** | ||||
* Sets a single source file to copy. | * Sets a single source file to copy. | ||||
*/ | */ | ||||
@@ -113,6 +115,15 @@ public class Copy extends Task { | |||||
this.destDir = destDir; | 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. | * 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); | 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. | * Sets filtering. | ||||
*/ | */ | ||||
@@ -338,11 +358,15 @@ public class Copy extends Task { | |||||
try { | try { | ||||
log("Copying " + fromFile + " to " + toFile, verbosity); | 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) { | } catch (IOException ioe) { | ||||
String msg = "Failed to copy " + fromFile + " to " + toFile | String msg = "Failed to copy " + fromFile + " to " + toFile | ||||
+ " due to " + ioe.getMessage(); | + " due to " + ioe.getMessage(); | ||||
@@ -100,7 +100,17 @@ public class Move extends Copy { | |||||
try { | try { | ||||
log("Moving " + fromFile + " to " + toFile, verbosity); | 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); | File f = new File(fromFile); | ||||
if (!f.delete()) { | if (!f.delete()) { | ||||
throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | 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 | fileset=org.apache.tools.ant.types.FileSet | ||||
patternset=org.apache.tools.ant.types.PatternSet | patternset=org.apache.tools.ant.types.PatternSet | ||||
mapper=org.apache.tools.ant.types.Mapper | mapper=org.apache.tools.ant.types.Mapper | ||||
filterset=org.apache.tools.ant.types.FilterSet | |||||