in src/main/org/apache/tools/ant/taskdefs/Copy.java [437:613]
public void execute() throws BuildException {
final File savedFile = file; // may be altered in validateAttributes
final File savedDestFile = destFile;
final File savedDestDir = destDir;
ResourceCollection savedRc = null;
if (file == null && destFile != null && rcs.size() == 1) {
// will be removed in validateAttributes
savedRc = rcs.elementAt(0);
}
try {
// make sure we don't have an illegal set of options
try {
validateAttributes();
} catch (final BuildException e) {
if (failonerror
|| !getMessage(e)
.equals(MSG_WHEN_COPYING_EMPTY_RC_TO_FILE)) {
throw e;
} else {
log("Warning: " + getMessage(e), Project.MSG_ERR);
return;
}
}
// deal with the single file
copySingleFile();
// deal with the ResourceCollections
/* for historical and performance reasons we have to do
things in a rather complex way.
(1) Move is optimized to move directories if a fileset
has been included completely, therefore FileSets need a
special treatment. This is also required to support
the failOnError semantic (skip filesets with broken
basedir but handle the remaining collections).
(2) We carry around a few protected methods that work
on basedirs and arrays of names. To optimize stuff, all
resources with the same basedir get collected in
separate lists and then each list is handled in one go.
*/
final Map<File, List<String>> filesByBasedir = new HashMap<>();
final Map<File, List<String>> dirsByBasedir = new HashMap<>();
final Set<File> baseDirs = new HashSet<>();
final List<Resource> nonFileResources = new ArrayList<>();
for (ResourceCollection rc : rcs) {
// Step (1) - beware of the ZipFileSet
if (rc instanceof FileSet && rc.isFilesystemOnly()) {
final FileSet fs = (FileSet) rc;
DirectoryScanner ds;
try {
ds = fs.getDirectoryScanner(getProject());
} catch (final BuildException e) {
if (failonerror
|| !getMessage(e).endsWith(DirectoryScanner
.DOES_NOT_EXIST_POSTFIX)) {
throw e;
}
if (!quiet) {
log("Warning: " + getMessage(e), Project.MSG_ERR);
}
continue;
}
final File fromDir = fs.getDir(getProject());
if (!flatten && mapperElement == null
&& ds.isEverythingIncluded() && !fs.hasPatterns()) {
completeDirMap.put(fromDir, destDir);
}
add(fromDir, ds.getIncludedFiles(), filesByBasedir);
add(fromDir, ds.getIncludedDirectories(), dirsByBasedir);
baseDirs.add(fromDir);
} else { // not a fileset or contains non-file resources
if (!rc.isFilesystemOnly() && !supportsNonFileResources()) {
throw new BuildException(
"Only FileSystem resources are supported.");
}
for (final Resource r : rc) {
if (!r.isExists()) {
final String message = "Warning: Could not find resource "
+ r.toLongString() + " to copy.";
if (!failonerror) {
if (!quiet) {
log(message, Project.MSG_ERR);
}
} else {
throw new BuildException(message);
}
continue;
}
File baseDir = NULL_FILE_PLACEHOLDER;
String name = r.getName();
final FileProvider fp = r.as(FileProvider.class);
if (fp != null) {
final FileResource fr = ResourceUtils.asFileResource(fp);
baseDir = getKeyFile(fr.getBaseDir());
if (fr.getBaseDir() == null) {
name = fr.getFile().getAbsolutePath();
}
}
// copying of dirs is trivial and can be done
// for non-file resources as well as for real
// files.
if (r.isDirectory() || fp != null) {
add(baseDir, name,
r.isDirectory() ? dirsByBasedir
: filesByBasedir);
baseDirs.add(baseDir);
} else { // a not-directory file resource
// needs special treatment
nonFileResources.add(r);
}
}
}
}
iterateOverBaseDirs(baseDirs, dirsByBasedir, filesByBasedir);
// do all the copy operations now...
try {
doFileOperations();
} catch (final BuildException e) {
if (!failonerror) {
if (!quiet) {
log("Warning: " + getMessage(e), Project.MSG_ERR);
}
} else {
throw e;
}
}
if (!nonFileResources.isEmpty() || singleResource != null) {
final Resource[] nonFiles =
nonFileResources.toArray(new Resource[0]);
// restrict to out-of-date resources
final Map<Resource, String[]> map = scan(nonFiles, destDir);
if (singleResource != null) {
map.put(singleResource,
new String[] {destFile.getAbsolutePath()});
}
try {
doResourceOperations(map);
} catch (final BuildException e) {
if (!failonerror) {
if (!quiet) {
log("Warning: " + getMessage(e), Project.MSG_ERR);
}
} else {
throw e;
}
}
}
} finally {
// clean up again, so this instance can be used a second
// time
singleResource = null;
file = savedFile;
destFile = savedDestFile;
destDir = savedDestDir;
if (savedRc != null) {
rcs.insertElementAt(savedRc, 0);
}
fileCopyMap.clear();
dirCopyMap.clear();
completeDirMap.clear();
}
}