public void execute()

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();
        }
    }