Method from org.apache.tools.ant.taskdefs.Copy Detail: |
public void add(ResourceCollection res) {
rcs.add(res);
}
Add a collection of files to copy. |
public void add(FileNameMapper fileNameMapper) {
createMapper().add(fileNameMapper);
}
Add a nested filenamemapper. |
public void addFileset(FileSet set) {
add(set);
}
Add a set of files to copy. |
protected Map buildMap(Resource[] fromResources,
File toDir,
FileNameMapper mapper) {
HashMap map = new HashMap();
Resource[] toCopy = null;
if (forceOverwrite) {
Vector v = new Vector();
for (int i = 0; i < fromResources.length; i++) {
if (mapper.mapFileName(fromResources[i].getName()) != null) {
v.addElement(fromResources[i]);
}
}
toCopy = new Resource[v.size()];
v.copyInto(toCopy);
} else {
toCopy =
ResourceUtils.selectOutOfDateSources(this, fromResources,
mapper,
new ResourceFactory() {
public Resource getResource(String name) {
return new FileResource(toDir, name);
}
},
granularity);
}
for (int i = 0; i < toCopy.length; i++) {
String[] mappedFiles = mapper.mapFileName(toCopy[i].getName());
for (int j = 0; j < mappedFiles.length; j++) {
if (mappedFiles[j] == null) {
throw new BuildException("Can't copy a resource without a"
+ " name if the mapper doesn't"
+ " provide one.");
}
}
if (!enableMultipleMappings) {
map.put(toCopy[i],
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(toCopy[i], mappedFiles);
}
}
return map;
}
Create a map of resources to copy. |
protected void buildMap(File fromDir,
File toDir,
String[] names,
FileNameMapper mapper,
Hashtable map) {
String[] toCopy = null;
if (forceOverwrite) {
Vector v = new Vector();
for (int i = 0; i < names.length; i++) {
if (mapper.mapFileName(names[i]) != null) {
v.addElement(names[i]);
}
}
toCopy = new String[v.size()];
v.copyInto(toCopy);
} else {
SourceFileScanner ds = new SourceFileScanner(this);
toCopy = ds.restrict(names, fromDir, toDir, mapper, granularity);
}
for (int i = 0; i < toCopy.length; i++) {
File src = new File(fromDir, toCopy[i]);
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);
}
}
}
Add to a map of files/directories to copy. |
public FilterChain createFilterChain() {
FilterChain filterChain = new FilterChain();
filterChains.addElement(filterChain);
return filterChain;
}
|
public FilterSet createFilterSet() {
FilterSet filterSet = new FilterSet();
filterSets.addElement(filterSet);
return filterSet;
}
|
public Mapper createMapper() throws BuildException {
if (mapperElement != null) {
throw new BuildException("Cannot define more than one mapper",
getLocation());
}
mapperElement = new Mapper(getProject());
return mapperElement;
}
Define the mapper to map source to destination files. |
protected void doFileOperations() {
if (fileCopyMap.size() > 0) {
log("Copying " + fileCopyMap.size()
+ " file" + (fileCopyMap.size() == 1 ? "" : "s")
+ " to " + destDir.getAbsolutePath());
Enumeration e = fileCopyMap.keys();
while (e.hasMoreElements()) {
String fromFile = (String) e.nextElement();
String[] toFiles = (String[]) fileCopyMap.get(fromFile);
for (int i = 0; i < toFiles.length; i++) {
String toFile = toFiles[i];
if (fromFile.equals(toFile)) {
log("Skipping self-copy of " + fromFile, verbosity);
continue;
}
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 " + getDueTo(ioe);
File targetFile = new File(toFile);
if (targetFile.exists() && !targetFile.delete()) {
msg += " and I couldn't delete the corrupt " + toFile;
}
if (failonerror) {
throw new BuildException(msg, ioe, getLocation());
}
log(msg, Project.MSG_ERR);
}
}
}
}
if (includeEmpty) {
Enumeration e = dirCopyMap.elements();
int createCount = 0;
while (e.hasMoreElements()) {
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 (createCount > 0) {
log("Copied " + dirCopyMap.size()
+ " empty director"
+ (dirCopyMap.size() == 1 ? "y" : "ies")
+ " to " + createCount
+ " empty director"
+ (createCount == 1 ? "y" : "ies") + " under "
+ destDir.getAbsolutePath());
}
}
}
Actually does the file (and possibly empty directory) copies.
This is a good method for subclasses to override. |
protected void doResourceOperations(Map map) {
if (map.size() > 0) {
log("Copying " + map.size()
+ " resource" + (map.size() == 1 ? "" : "s")
+ " to " + destDir.getAbsolutePath());
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Resource fromResource = (Resource) iter.next();
String[] toFiles = (String[]) map.get(fromResource);
for (int i = 0; i < toFiles.length; i++) {
String toFile = toFiles[i];
try {
log("Copying " + fromResource + " 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());
}
ResourceUtils.copyResource(fromResource,
new FileResource(destDir,
toFile),
executionFilters,
filterChains,
forceOverwrite,
preserveLastModified,
inputEncoding,
outputEncoding,
getProject());
} catch (IOException ioe) {
String msg = "Failed to copy " + fromResource
+ " to " + toFile
+ " due to " + getDueTo(ioe);
File targetFile = new File(toFile);
if (targetFile.exists() && !targetFile.delete()) {
msg += " and I couldn't delete the corrupt " + toFile;
}
if (failonerror) {
throw new BuildException(msg, ioe, getLocation());
}
log(msg, Project.MSG_ERR);
}
}
}
}
}
Actually does the resource copies.
This is a good method for subclasses to override. |
public void execute() throws BuildException {
File savedFile = file; // may be altered in validateAttributes
File savedDestFile = destFile;
File savedDestDir = destDir;
ResourceCollection savedRc = null;
if (file == null && destFile != null && rcs.size() == 1) {
// will be removed in validateAttributes
savedRc = (ResourceCollection) rcs.elementAt(0);
}
try {
// make sure we don't have an illegal set of options
try {
validateAttributes();
} catch (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 semantice (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.
*/
HashMap filesByBasedir = new HashMap();
HashMap dirsByBasedir = new HashMap();
HashSet baseDirs = new HashSet();
ArrayList nonFileResources = new ArrayList();
for (int i = 0; i < rcs.size(); i++) {
ResourceCollection rc = (ResourceCollection) rcs.elementAt(i);
// Step (1) - beware of the ZipFileSet
if (rc instanceof FileSet && rc.isFilesystemOnly()) {
FileSet fs = (FileSet) rc;
DirectoryScanner ds = null;
try {
ds = fs.getDirectoryScanner(getProject());
} catch (BuildException e) {
if (failonerror
|| !getMessage(e).endsWith(DirectoryScanner
.DOES_NOT_EXIST_POSTFIX)) {
throw e;
} else {
log("Warning: " + getMessage(e), Project.MSG_ERR);
continue;
}
}
File fromDir = fs.getDir(getProject());
String[] srcFiles = ds.getIncludedFiles();
String[] srcDirs = ds.getIncludedDirectories();
if (!flatten && mapperElement == null
&& ds.isEverythingIncluded() && !fs.hasPatterns()) {
completeDirMap.put(fromDir, destDir);
}
add(fromDir, srcFiles, filesByBasedir);
add(fromDir, srcDirs, 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.");
}
Iterator resources = rc.iterator();
while (resources.hasNext()) {
Resource r = (Resource) resources.next();
if (!r.isExists()) {
String message = "Warning: Could not find resource "
+ r.toLongString() + " to copy.";
if (!failonerror) {
log(message, Project.MSG_ERR);
} else {
throw new BuildException(message);
}
continue;
}
File baseDir = NULL_FILE_PLACEHOLDER;
String name = r.getName();
FileProvider fp = (FileProvider) r.as(FileProvider.class);
if (fp != null) {
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 (BuildException e) {
if (!failonerror) {
log("Warning: " + getMessage(e), Project.MSG_ERR);
} else {
throw e;
}
}
if (nonFileResources.size() > 0) {
Resource[] nonFiles =
(Resource[]) nonFileResources.toArray(new Resource[nonFileResources.size()]);
// restrict to out-of-date resources
Map map = scan(nonFiles, destDir);
try {
doResourceOperations(map);
} catch (BuildException e) {
if (!failonerror) {
log("Warning: " + getMessage(e), Project.MSG_ERR);
} else {
throw e;
}
}
}
} finally {
// clean up again, so this instance can be used a second
// time
file = savedFile;
destFile = savedDestFile;
destDir = savedDestDir;
if (savedRc != null) {
rcs.insertElementAt(savedRc, 0);
}
fileCopyMap.clear();
dirCopyMap.clear();
completeDirMap.clear();
}
}
Perform the copy operation. |
public String getEncoding() {
return inputEncoding;
}
Get the character encoding to be used. |
protected FileUtils getFileUtils() {
return fileUtils;
}
Get the FileUtils for this task. |
protected Vector getFilterChains() {
return filterChains;
}
Get the filterchains being applied to this operation. |
protected Vector getFilterSets() {
return filterSets;
}
Get the filtersets being applied to this operation. |
public String getOutputEncoding() {
return outputEncoding;
}
Get the character encoding for output files. |
public boolean getPreserveLastModified() {
return preserveLastModified;
}
Get whether to give the copied files the same last modified time as
the original files. |
public boolean isEnableMultipleMapping() {
return enableMultipleMappings;
}
Get whether multiple mapping is enabled. |
protected Map scan(Resource[] fromResources,
File toDir) {
return buildMap(fromResources, toDir, getMapper());
}
Compares source resources to destination files to see if they
should be copied. |
protected void scan(File fromDir,
File toDir,
String[] files,
String[] dirs) {
FileNameMapper mapper = getMapper();
buildMap(fromDir, toDir, files, mapper, fileCopyMap);
if (includeEmpty) {
buildMap(fromDir, toDir, dirs, mapper, dirCopyMap);
}
}
Compares source files to destination files to see if they should be
copied. |
public void setEnableMultipleMappings(boolean enableMultipleMappings) {
this.enableMultipleMappings = enableMultipleMappings;
}
Set method of handling mappers that return multiple
mappings for a given source path. |
public void setEncoding(String encoding) {
this.inputEncoding = encoding;
if (outputEncoding == null) {
outputEncoding = encoding;
}
}
Set the character encoding. |
public void setFailOnError(boolean failonerror) {
this.failonerror = failonerror;
}
Set whether to fail when errors are encountered. If false, note errors
to the output but keep going. Default is true. |
public void setFile(File file) {
this.file = file;
}
Set a single source file to copy. |
public void setFiltering(boolean filtering) {
this.filtering = filtering;
}
|
public void setFlatten(boolean flatten) {
this.flatten = flatten;
}
Set whether files copied from directory trees will be "flattened"
into a single directory. If there are multiple files with
the same name in the source directory tree, only the first
file will be copied into the "flattened" directory, unless
the forceoverwrite attribute is true. |
public void setGranularity(long granularity) {
this.granularity = granularity;
}
Set the number of milliseconds leeway to give before deciding a
target is out of date.
Default is 1 second, or 2 seconds on DOS systems. |
public void setIncludeEmptyDirs(boolean includeEmpty) {
this.includeEmpty = includeEmpty;
}
Set whether to copy empty directories. |
public void setOutputEncoding(String encoding) {
this.outputEncoding = encoding;
}
Set the character encoding for output files. |
public void setOverwrite(boolean overwrite) {
this.forceOverwrite = overwrite;
}
Set overwrite mode regarding existing destination file(s). |
public void setPreserveLastModified(String preserve) {
setPreserveLastModified(Project.toBoolean(preserve));
} Deprecated! since - 1.5.x.
setPreserveLastModified(String) has been deprecated and
replaced with setPreserveLastModified(boolean) to
consistently let the Introspection mechanism work.
Give the copied files the same last modified time as the original files. |
public void setPreserveLastModified(boolean preserve) {
preserveLastModified = preserve;
}
Give the copied files the same last modified time as the original files. |
public void setTodir(File destDir) {
this.destDir = destDir;
}
Set the destination directory. |
public void setTofile(File destFile) {
this.destFile = destFile;
}
Set the destination file. |
public void setVerbose(boolean verbose) {
this.verbosity = verbose ? Project.MSG_INFO : Project.MSG_VERBOSE;
}
Set verbose mode. Used to force listing of all names of copied files. |
protected boolean supportsNonFileResources() {
return getClass().equals(Copy.class);
}
Whether this task can deal with non-file resources.
<copy> can while <move> can't since we don't
know how to remove non-file resources.
This implementation returns true only if this task is
<copy>. Any subclass of this class that also wants to
support non-file resources needs to override this method. We
need to do so for backwards compatibility reasons since we
can't expect subclasses to support resources. |
protected void validateAttributes() throws BuildException {
if (file == null && rcs.size() == 0) {
throw new BuildException(
"Specify at least one source--a file or a resource collection.");
}
if (destFile != null && destDir != null) {
throw new BuildException(
"Only one of tofile and todir may be set.");
}
if (destFile == null && destDir == null) {
throw new BuildException("One of tofile or todir must be set.");
}
if (file != null && file.isDirectory()) {
throw new BuildException("Use a resource collection to copy directories.");
}
if (destFile != null && rcs.size() > 0) {
if (rcs.size() > 1) {
throw new BuildException(
"Cannot concatenate multiple files into a single file.");
} else {
ResourceCollection rc = (ResourceCollection) rcs.elementAt(0);
if (!rc.isFilesystemOnly()) {
throw new BuildException("Only FileSystem resources are"
+ " supported when concatenating"
+ " files.");
}
if (rc.size() == 0) {
throw new BuildException(MSG_WHEN_COPYING_EMPTY_RC_TO_FILE);
} else if (rc.size() == 1) {
Resource res = (Resource) rc.iterator().next();
FileProvider r = (FileProvider) res.as(FileProvider.class);
if (file == null) {
file = r.getFile();
rcs.removeElementAt(0);
} else {
throw new BuildException(
"Cannot concatenate multiple files into a single file.");
}
} else {
throw new BuildException(
"Cannot concatenate multiple files into a single file.");
}
}
}
if (destFile != null) {
destDir = destFile.getParentFile();
}
}
Ensure we have a consistent and legal set of attributes, and set
any internal flags necessary based on different combinations
of attributes. |