From 99067d060752e5a89c24d99c17b6eb7231f96380 Mon Sep 17 00:00:00 2001
From: Peter Reilly
Date: Thu, 24 Jul 2003 13:14:21 +0000
Subject: [PATCH] Add multimapping to the copy and move task Some slight
changes from the orignal patch - rename of ignoremultiplemapping to
enablemultiplemapping and some checkstyle changes PR: 21320 Obtained from:
Evan Easton
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274923 13f79535-47bb-0310-9956-ffa450edef68
---
docs/manual/CoreTasks/copy.html | 17 ++
docs/manual/CoreTasks/move.html | 10 +
src/etc/testcases/taskdefs/multimap.xml | 175 ++++++++++++++++
.../org/apache/tools/ant/taskdefs/Copy.java | 137 ++++++++-----
.../org/apache/tools/ant/taskdefs/Move.java | 189 +++++++++++-------
.../tools/ant/taskdefs/MultiMapTest.java | 114 +++++++++++
6 files changed, 527 insertions(+), 115 deletions(-)
create mode 100644 src/etc/testcases/taskdefs/multimap.xml
create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/MultiMapTest.java
diff --git a/docs/manual/CoreTasks/copy.html b/docs/manual/CoreTasks/copy.html
index 93f6ee428..e49ca8882 100644
--- a/docs/manual/CoreTasks/copy.html
+++ b/docs/manual/CoreTasks/copy.html
@@ -118,6 +118,23 @@ operation as filtersets
No - defaults to the value of the encoding
attribute if given or the default JVM encoding otherwise. |
+
+ outputencoding |
+ The encoding to use when writing the files.
+ since Ant 1.6. |
+ No - defaults to the value of the encoding
+ attribute if given or the default JVM encoding otherwise. |
+
+
+ enablemultiplemapping |
+
+ If true the task will process to all the mappings for a
+ given source path. If false the task will only process
+ the first file or directory. This attribute is only relevant
+ if there is a mapper subelement.
+ since Ant 1.6. |
+ No - defaults to false. |
+
Parameters specified as nested elements
diff --git a/docs/manual/CoreTasks/move.html b/docs/manual/CoreTasks/move.html
index b05000513..bb3235155 100644
--- a/docs/manual/CoreTasks/move.html
+++ b/docs/manual/CoreTasks/move.html
@@ -103,6 +103,16 @@ to move to the todir directory.
No - defaults to the value of the encoding
attribute if given or the default JVM encoding otherwise. |
+
+ enablemultiplemapping |
+
+ If true the task will process to all the mappings for a
+ given source path. If false the task will only process
+ the first file or directory. This attribute is only relevant
+ if there is a mapper subelement.
+ since Ant 1.6. |
+ No - defaults to false. |
+
Parameters specified as nested elements
mapper
diff --git a/src/etc/testcases/taskdefs/multimap.xml b/src/etc/testcases/taskdefs/multimap.xml
new file mode 100644
index 000000000..5911197c1
--- /dev/null
+++ b/src/etc/testcases/taskdefs/multimap.xml
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ multicopy failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mulitmove failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ singlecopy failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ singlemove failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ copywithempty failed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ movewithempty failed
+
+
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/Copy.java b/src/main/org/apache/tools/ant/taskdefs/Copy.java
index 716e37f81..5b0c53234 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Copy.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Copy.java
@@ -102,6 +102,7 @@ public class Copy extends Task {
protected File destDir = null; // the destination directory
protected Vector filesets = new Vector();
+ private boolean enableMultipleMappings = false;
protected boolean filtering = false;
protected boolean preserveLastModified = false;
protected boolean forceOverwrite = false;
@@ -259,6 +260,28 @@ public class Copy extends Task {
this.includeEmpty = includeEmpty;
}
+ /**
+ * Attribute to handle mappers that return multiple
+ * mappings for a given source path.
+ * @param enableMultipleMappings If true the task will
+ * copy to all the mappings for a given source path, if
+ * false, only the first file or directory is
+ * processed.
+ * By default, this setting is false to provide backward
+ * compatibility with earlier releases.
+ * @since 1.6
+ */
+ public void setEnableMultipleMappings(boolean enableMultipleMappings) {
+ this.enableMultipleMappings = enableMultipleMappings;
+ }
+
+ /**
+ * @return the value of the enableMultipleMapping attribute
+ */
+ public boolean isEnableMultipleMapping() {
+ return enableMultipleMappings;
+ }
+
/**
* If false, note errors to the output but keep going.
* @param failonerror true or false
@@ -354,7 +377,7 @@ public class Copy extends Task {
if (forceOverwrite || !destFile.exists()
|| (file.lastModified() > destFile.lastModified())) {
fileCopyMap.put(file.getAbsolutePath(),
- destFile.getAbsolutePath());
+ new String[] {destFile.getAbsolutePath()});
} else {
log(file + " omitted as " + destFile
+ " is up to date.", Project.MSG_VERBOSE);
@@ -528,8 +551,20 @@ public class Copy extends Task {
for (int i = 0; i < toCopy.length; i++) {
File src = new File(fromDir, toCopy[i]);
- File dest = new File(toDir, mapper.mapFileName(toCopy[i])[0]);
- map.put(src.getAbsolutePath(), dest.getAbsolutePath());
+
+ String[] mappedFiles = mapper.mapFileName(toCopy[i]);
+
+ if (!enableMultipleMappings) {
+ map.put(src.getAbsolutePath(),
+ new String[] {new File(toDir, mappedFiles[0]).getAbsolutePath()});
+ } else {
+ // reuse the array created by the mapper
+ for (int k = 0; k < mappedFiles.length; k++) {
+ mappedFiles[k] = new File(toDir, mappedFiles[k]).getAbsolutePath();
+ }
+
+ map.put(src.getAbsolutePath(), mappedFiles);
+ }
}
}
@@ -546,64 +581,74 @@ public class Copy extends Task {
Enumeration e = fileCopyMap.keys();
while (e.hasMoreElements()) {
String fromFile = (String) e.nextElement();
- String toFile = (String) fileCopyMap.get(fromFile);
-
- if (fromFile.equals(toFile)) {
- log("Skipping self-copy of " + fromFile, verbosity);
- continue;
- }
+ String[] toFiles = (String[]) fileCopyMap.get(fromFile);
- try {
- log("Copying " + fromFile + " to " + toFile, verbosity);
+ for (int i = 0; i < toFiles.length; i++) {
+ String toFile = toFiles[i];
- FilterSetCollection executionFilters =
- new FilterSetCollection();
- if (filtering) {
- executionFilters
- .addFilterSet(getProject().getGlobalFilterSet());
- }
- for (Enumeration filterEnum = filterSets.elements();
- filterEnum.hasMoreElements();) {
- executionFilters
- .addFilterSet((FilterSet) filterEnum.nextElement());
+ if (fromFile.equals(toFile)) {
+ log("Skipping self-copy of " + fromFile, verbosity);
+ continue;
}
- fileUtils.copyFile(fromFile, toFile, executionFilters,
- filterChains, forceOverwrite,
- preserveLastModified, inputEncoding,
- outputEncoding, getProject());
- } catch (IOException ioe) {
- String msg = "Failed to copy " + fromFile + " to " + toFile
- + " due to " + ioe.getMessage();
- File targetFile = new File(toFile);
- if (targetFile.exists() && !targetFile.delete()) {
- msg += " and I couldn't delete the corrupt " + toFile;
+
+ try {
+ log("Copying " + fromFile + " to " + toFile, verbosity);
+
+ FilterSetCollection executionFilters =
+ new FilterSetCollection();
+ if (filtering) {
+ executionFilters
+ .addFilterSet(getProject().getGlobalFilterSet());
+ }
+ for (Enumeration filterEnum = filterSets.elements();
+ filterEnum.hasMoreElements();) {
+ executionFilters
+ .addFilterSet((FilterSet) filterEnum.nextElement());
+ }
+ fileUtils.copyFile(fromFile, toFile, executionFilters,
+ filterChains, forceOverwrite,
+ preserveLastModified, inputEncoding,
+ outputEncoding, getProject());
+ } catch (IOException ioe) {
+ String msg = "Failed to copy " + fromFile + " to " + toFile
+ + " due to " + ioe.getMessage();
+ File targetFile = new File(toFile);
+ if (targetFile.exists() && !targetFile.delete()) {
+ msg += " and I couldn't delete the corrupt " + toFile;
+ }
+ throw new BuildException(msg, ioe, getLocation());
}
- throw new BuildException(msg, ioe, getLocation());
}
}
}
if (includeEmpty) {
Enumeration e = dirCopyMap.elements();
- int count = 0;
+ int createCount = 0;
while (e.hasMoreElements()) {
- File d = new File((String) e.nextElement());
- if (!d.exists()) {
- if (!d.mkdirs()) {
- log("Unable to create directory "
- + d.getAbsolutePath(), Project.MSG_ERR);
- } else {
- count++;
+ String[] dirs = (String[]) e.nextElement();
+ for (int i = 0; i < dirs.length; i++) {
+ File d = new File(dirs[i]);
+ if (!d.exists()) {
+ if (!d.mkdirs()) {
+ log("Unable to create directory "
+ + d.getAbsolutePath(), Project.MSG_ERR);
+ } else {
+ createCount++;
+ }
}
}
}
-
- if (count > 0) {
- log("Copied " + count + " empty director"
- + (count == 1 ? "y" : "ies")
- + " to " + destDir.getAbsolutePath());
+ if (createCount > 0) {
+ log("Copied " + dirCopyMap.size()
+ + " empty director"
+ + (dirCopyMap.size() == 1 ? "y" : "ies")
+ + " to " + createCount
+ + " empty director"
+ + (createCount == 1 ? "y" : "ies") + " under "
+ + destDir.getAbsolutePath());
}
}
}
-
}
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/Move.java b/src/main/org/apache/tools/ant/taskdefs/Move.java
index cda100a5c..d9f83c2ac 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Move.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Move.java
@@ -125,67 +125,29 @@ public class Move extends Copy {
Enumeration e = fileCopyMap.keys();
while (e.hasMoreElements()) {
String fromFile = (String) e.nextElement();
- String toFile = (String) fileCopyMap.get(fromFile);
- if (fromFile.equals(toFile)) {
- log("Skipping self-move of " + fromFile, verbosity);
- continue;
- }
-
- boolean moved = false;
File f = new File(fromFile);
-
+ boolean selfMove = false;
if (f.exists()) { //Is this file still available to be moved?
- File d = new File(toFile);
-
- try {
- log("Attempting to rename: " + fromFile
- + " to " + toFile, verbosity);
- moved = renameFile(f, d, filtering, forceOverwrite);
- } catch (IOException ioe) {
- String msg = "Failed to rename " + fromFile
- + " to " + toFile
- + " due to " + ioe.getMessage();
- throw new BuildException(msg, ioe, getLocation());
- }
+ String[] toFiles = (String[]) fileCopyMap.get(fromFile);
+ for (int i = 0; i < toFiles.length; i++) {
+ String toFile = (String) toFiles[i];
- if (!moved) {
- try {
- log("Moving " + fromFile + " to " + toFile,
- verbosity);
+ if (fromFile.equals(toFile)) {
+ log("Skipping self-move of " + fromFile, verbosity);
+ selfMove = true;
- FilterSetCollection executionFilters =
- new FilterSetCollection();
- if (filtering) {
- executionFilters
- .addFilterSet(getProject().getGlobalFilterSet());
- }
- for (Enumeration filterEnum =
- getFilterSets().elements();
- filterEnum.hasMoreElements();) {
- executionFilters
- .addFilterSet((FilterSet) filterEnum
- .nextElement());
- }
- getFileUtils().copyFile(f, d, executionFilters,
- getFilterChains(),
- forceOverwrite,
- getPreserveLastModified(),
- getEncoding(),
- getOutputEncoding(),
- getProject());
-
- f = new File(fromFile);
- if (!f.delete()) {
- throw new BuildException("Unable to delete "
- + "file "
- + f.getAbsolutePath());
- }
- } catch (IOException ioe) {
- String msg = "Failed to copy " + fromFile + " to "
- + toFile
- + " due to " + ioe.getMessage();
- throw new BuildException(msg, ioe, getLocation());
+ // if this is the last time through the loop then
+ // move will not occur, but that's what we want
+ continue;
+ }
+ File d = new File(toFile);
+ if ((i + 1) == toFiles.length && !selfMove) {
+ // Only try to move if this is the last mapped file
+ // and one of the mappings isn't to itself
+ moveFile(f, d, filtering, forceOverwrite);
+ } else {
+ copyFile(f, d, filtering, forceOverwrite);
}
}
}
@@ -194,32 +156,121 @@ public class Move extends Copy {
if (includeEmpty) {
Enumeration e = dirCopyMap.keys();
- int count = 0;
+ int createCount = 0;
while (e.hasMoreElements()) {
String fromDirName = (String) e.nextElement();
- String toDirName = (String) dirCopyMap.get(fromDirName);
- File fromDir = new File(fromDirName);
- File toDir = new File(toDirName);
- if (!toDir.exists()) {
- if (!toDir.mkdirs()) {
- log("Unable to create directory "
- + toDirName, Project.MSG_ERR);
- } else {
- count++;
+ String[] toDirNames = (String[]) dirCopyMap.get(fromDirName);
+ boolean selfMove = false;
+ for (int i = 0; i < toDirNames.length; i++) {
+
+ if (fromDirName.equals(toDirNames[i])) {
+ log("Skipping self-move of " + fromDirName, verbosity);
+ selfMove = true;
+ continue;
+ }
+
+ File d = new File(toDirNames[i]);
+ if (!d.exists()) {
+ if (!d.mkdirs()) {
+ log("Unable to create directory "
+ + d.getAbsolutePath(), Project.MSG_ERR);
+ } else {
+ createCount++;
+ }
}
}
- if (okToDelete(fromDir)) {
+
+ File fromDir = new File(fromDirName);
+ if (!selfMove && okToDelete(fromDir)) {
deleteDir(fromDir);
}
+
}
- if (count > 0) {
- log("Moved " + count + " empty directories to "
+ if (createCount > 0) {
+ log("Moved " + dirCopyMap.size()
+ + " empty director"
+ + (dirCopyMap.size()== 1 ? "y" : "ies")
+ + " to " + createCount
+ + " empty director"
+ + (createCount == 1 ? "y" : "ies") + " under "
+ destDir.getAbsolutePath());
}
}
}
+ /**
+ * Try to move the file via a rename, but if this fails or filtering
+ * is enabled, copy the file then delete the sourceFile.
+ */
+ private void moveFile(File fromFile, File toFile,
+ boolean filtering, boolean overwrite) {
+ boolean moved = false;
+ try {
+ log("Attempting to rename: " + fromFile
+ + " to " + toFile, verbosity);
+ moved = renameFile(fromFile, toFile, filtering, forceOverwrite);
+ } catch (IOException ioe) {
+ String msg = "Failed to rename " + fromFile
+ + " to " + toFile
+ + " due to " + ioe.getMessage();
+ throw new BuildException(msg, ioe, getLocation());
+ }
+
+ if (!moved) {
+ copyFile(fromFile, toFile, filtering, overwrite);
+ if (!fromFile.delete()) {
+ throw new BuildException("Unable to delete "
+ + "file "
+ + fromFile.getAbsolutePath());
+ }
+ }
+ }
+
+ /**
+ * Copy fromFile to toFile.
+ * @param fromFile
+ * @param toFile
+ * @param filtering
+ * @param overwrite
+ */
+ private void copyFile(File fromFile, File toFile,
+ boolean filtering, boolean overwrite) {
+ try {
+ log("Copying " + fromFile + " to " + toFile,
+ verbosity);
+
+ FilterSetCollection executionFilters =
+ new FilterSetCollection();
+ if (filtering) {
+ executionFilters
+ .addFilterSet(getProject().getGlobalFilterSet());
+ }
+ for (Enumeration filterEnum =
+ getFilterSets().elements();
+ filterEnum.hasMoreElements();) {
+ executionFilters
+ .addFilterSet((FilterSet) filterEnum
+ .nextElement());
+ }
+
+ getFileUtils().copyFile(fromFile, toFile, executionFilters,
+ getFilterChains(),
+ forceOverwrite,
+ getPreserveLastModified(),
+ getEncoding(),
+ getOutputEncoding(),
+ getProject());
+
+ } catch (IOException ioe) {
+ String msg = "Failed to copy " + fromFile
+ + " to " + toFile
+ + " due to " + ioe.getMessage();
+ throw new BuildException(msg, ioe, getLocation());
+ }
+ }
+
+
/**
* Its only ok to delete a directory tree if there are
* no files in it.
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/MultiMapTest.java b/src/testcases/org/apache/tools/ant/taskdefs/MultiMapTest.java
new file mode 100644
index 000000000..2e8f12192
--- /dev/null
+++ b/src/testcases/org/apache/tools/ant/taskdefs/MultiMapTest.java
@@ -0,0 +1,114 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "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.taskdefs;
+
+import java.lang.reflect.Method;
+
+import org.apache.tools.ant.BuildFileTest;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.FileNameMapper;
+
+
+/**
+ * @author Peter Reilly
+ */
+public class MultiMapTest extends BuildFileTest {
+
+ public MultiMapTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("src/etc/testcases/taskdefs/multimap.xml");
+ }
+
+ public void tearDown() {
+ executeTarget("cleanup");
+ }
+
+ public void testMultiCopy() {
+ executeTarget("multicopy");
+ }
+
+ public void testMultiMove() {
+ executeTarget("multimove");
+ }
+
+ public void testSingleCopy() {
+ executeTarget("singlecopy");
+ }
+
+ public void testSingleMove() {
+ executeTarget("singlemove");
+ }
+
+ public void testCopyWithEmpty() {
+ executeTarget("copywithempty");
+ }
+
+ public void testMoveWithEmpty() {
+ executeTarget("movewithempty");
+ }
+
+ public static class TestMapper implements FileNameMapper {
+ public TestMapper() {}
+ public void setFrom(String from) {}
+ public void setTo(String to) {}
+ public String[] mapFileName(final String source_file_name) {
+ return new String[] {
+ source_file_name, source_file_name+".copy2" };
+ }
+ }
+}