001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import org.apache.tools.ant.BuildException;
022: import org.apache.tools.ant.Project;
023: import org.apache.tools.ant.Task;
024: import org.apache.tools.ant.util.FileUtils;
025: import org.apache.tools.ant.util.FileNameMapper;
026: import org.apache.tools.ant.types.Path;
027: import org.apache.tools.ant.types.Reference;
028:
029: import java.io.File;
030: import java.io.IOException;
031:
032: /**
033: * Copy the contents of a path to a destination, using the mapper of choice
034: *
035: * @since Ant 1.7
036: *
037: * @ant.task category="filesystem"
038: */
039:
040: public class CopyPath extends Task {
041:
042: // Error messages
043: /** No destdir attribute */
044: public static final String ERROR_NO_DESTDIR = "No destDir specified";
045:
046: /** No path */
047: public static final String ERROR_NO_PATH = "No path specified";
048:
049: /** No mapper */
050: public static final String ERROR_NO_MAPPER = "No mapper specified";
051:
052: // fileutils
053: private static final FileUtils FILE_UTILS = FileUtils
054: .getFileUtils();
055:
056: // --- Fields --
057: private FileNameMapper mapper;
058:
059: private Path path;
060:
061: private File destDir;
062:
063: // TODO not read, yet in a public setter
064: private long granularity = FILE_UTILS.getFileTimestampGranularity();
065:
066: private boolean preserveLastModified = false;
067:
068: /**
069: * The dest dir attribute.
070: * @param destDir the value of the destdir attribute.
071: */
072: public void setDestDir(File destDir) {
073: this .destDir = destDir;
074: }
075:
076: /**
077: * add a mapper
078: *
079: * @param newmapper the mapper to add.
080: */
081: public void add(FileNameMapper newmapper) {
082: if (mapper != null) {
083: throw new BuildException("Only one mapper allowed");
084: }
085: mapper = newmapper;
086: }
087:
088: /**
089: * Set the path to be used when running the Java class.
090: *
091: * @param s
092: * an Ant Path object containing the path.
093: */
094: public void setPath(Path s) {
095: createPath().append(s);
096: }
097:
098: /**
099: * Set the path to use by reference.
100: *
101: * @param r
102: * a reference to an existing path.
103: */
104: public void setPathRef(Reference r) {
105: createPath().setRefid(r);
106: }
107:
108: /**
109: * Create a path.
110: *
111: * @return a path to be configured.
112: */
113: public Path createPath() {
114: if (path == null) {
115: path = new Path(getProject());
116: }
117: return path;
118: }
119:
120: /**
121: * Set the number of milliseconds leeway to give before deciding a
122: * target is out of date.
123: * TODO: This is not yet used.
124: * @param granularity the granularity used to decide if a target is out of
125: * date.
126: */
127: public void setGranularity(long granularity) {
128: this .granularity = granularity;
129: }
130:
131: /**
132: * Give the copied files the same last modified time as the original files.
133: * @param preserveLastModified if true preserve the modified time;
134: * default is false.
135: */
136: public void setPreserveLastModified(boolean preserveLastModified) {
137: this .preserveLastModified = preserveLastModified;
138: }
139:
140: /**
141: * Ensure we have a consistent and legal set of attributes, and set any
142: * internal flags necessary based on different combinations of attributes.
143: *
144: * @throws BuildException
145: * if an error occurs.
146: */
147: protected void validateAttributes() throws BuildException {
148: if (destDir == null) {
149: throw new BuildException(ERROR_NO_DESTDIR);
150: }
151: if (mapper == null) {
152: throw new BuildException(ERROR_NO_MAPPER);
153: }
154: if (path == null) {
155: throw new BuildException(ERROR_NO_PATH);
156: }
157: }
158:
159: /**
160: * This is a very minimal derivative of the nomal copy logic.
161: *
162: * @throws BuildException
163: * if something goes wrong with the build.
164: */
165: public void execute() throws BuildException {
166: validateAttributes();
167: String[] sourceFiles = path.list();
168: if (sourceFiles.length == 0) {
169: log("Path is empty", Project.MSG_VERBOSE);
170: return;
171: }
172:
173: for (int sources = 0; sources < sourceFiles.length; sources++) {
174:
175: String sourceFileName = sourceFiles[sources];
176: File sourceFile = new File(sourceFileName);
177: String[] toFiles = (String[]) mapper
178: .mapFileName(sourceFileName);
179:
180: for (int i = 0; i < toFiles.length; i++) {
181: String destFileName = toFiles[i];
182: File destFile = new File(destDir, destFileName);
183:
184: if (sourceFile.equals(destFile)) {
185: log("Skipping self-copy of " + sourceFileName,
186: Project.MSG_VERBOSE);
187: continue;
188: }
189: if (sourceFile.isDirectory()) {
190: log("Skipping directory " + sourceFileName);
191: continue;
192: }
193: try {
194: log("Copying " + sourceFile + " to " + destFile,
195: Project.MSG_VERBOSE);
196:
197: FILE_UTILS.copyFile(sourceFile, destFile, null,
198: null, false, preserveLastModified, null,
199: null, getProject());
200: } catch (IOException ioe) {
201: String msg = "Failed to copy " + sourceFile
202: + " to " + destFile + " due to "
203: + ioe.getMessage();
204: if (destFile.exists() && !destFile.delete()) {
205: msg += " and I couldn't delete the corrupt "
206: + destFile;
207: }
208: throw new BuildException(msg, ioe, getLocation());
209: }
210: }
211: }
212: }
213: }
|