You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by mb...@apache.org on 2005/02/03 18:58:11 UTC
cvs commit: ant/src/main/org/apache/tools/ant/taskdefs/optional/unix Symlink.java
mbenson 2005/02/03 09:58:11
Modified: src/main/org/apache/tools/ant/taskdefs/optional/unix
Symlink.java
Log:
Revamp symlink task:
Extend DispatchTask
Remove 1.1 stuff / use 1.2 features where helpful
Javadoc & bumming
Revision Changes Path
1.23 +262 -407 ant/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
Index: Symlink.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- Symlink.java 28 Jan 2005 16:12:37 -0000 1.22
+++ Symlink.java 3 Feb 2005 17:58:11 -0000 1.23
@@ -30,27 +30,33 @@
import java.io.File;
import java.io.IOException;
+import java.io.PrintStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.util.Vector;
-import java.util.Properties;
-import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Hashtable;
+import java.util.Properties;
import org.apache.tools.ant.Task;
+import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
-
-import org.apache.tools.ant.util.FileUtils;
-
-import org.apache.tools.ant.types.FileSet;
-
+import org.apache.tools.ant.dispatch.DispatchTask;
+import org.apache.tools.ant.dispatch.DispatchUtils;
import org.apache.tools.ant.taskdefs.Execute;
+import org.apache.tools.ant.taskdefs.LogOutputStream;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.util.FileUtils;
/**
- * Creates, Records and Restores Symlinks.
+ * Creates, Deletes, Records and Restores Symlinks.
*
* <p> This task performs several related operations. In the most trivial
* and default usage, it creates a link specified in the link attribute to
@@ -61,10 +67,9 @@
* directory structure specified by a fileset, looking for properties files
* (also specified as included in the fileset) and recreate the links
* that have been previously recorded for each directory. Finally, it can be
- * used to remove a symlink without deleting the file or directory it points
- * to.
+ * used to remove a symlink without deleting the associated resource.
*
- * <p> Examples of use:
+ * <p> Usage examples:
*
* <p> Make a link named "foo" to a resource named
* "bar.foo" in subdir:
@@ -73,7 +78,7 @@
* </pre>
*
* <p> Record all links in subdir and its descendants in files named
- * "dir.links"
+ * "dir.links":
* <pre>
* <symlink action="record" linkfilename="dir.links">
* <fileset dir="${dir.top}" includes="subdir/**" />
@@ -98,7 +103,7 @@
* absolute paths. On non-unix systems this may cause false positives.
* Furthermore, any operating system on which the command
* <code>ln -s link resource</code> is not a valid command on the command line
- * will not be able to use action= "delete", action="single"
+ * will not be able to use action="delete", action="single"
* or action="recreate", but action="record" should still
* work. Finally, the lack of support for symlinks in Java means that all links
* are recorded as links to the <strong>canonical</strong> resource name.
@@ -108,18 +113,16 @@
*
* @version $Revision$
*/
-public class Symlink extends Task {
+public class Symlink extends DispatchTask {
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
- // Attributes with setter methods:
private String resource;
private String link;
- private String action;
private Vector fileSets = new Vector();
private String linkFileName;
private boolean overwrite;
private boolean failonerror;
-
- private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+ private boolean executing = false;
/**
* Initialize the task.
@@ -127,146 +130,169 @@
*/
public void init() throws BuildException {
super.init();
- failonerror = true; // default behavior is to fail on an error
- overwrite = false; // default behavior is to not overwrite
- action = "single"; // default behavior is make a single link
- fileSets = new Vector();
+ setDefaults();
}
/**
* The standard method for executing any task.
* @throws BuildException on error.
*/
- public void execute() throws BuildException {
+ public synchronized void execute() throws BuildException {
+ if (executing) {
+ throw new BuildException(
+ "Infinite recursion detected in Symlink.execute()");
+ }
+ try {
+ executing = true;
+ DispatchUtils.execute(this);
+ } finally {
+ executing = false;
+ }
+ }
+
+ /**
+ * Create a symlink.
+ * @throws BuildException on error.
+ */
+ public void single() throws BuildException {
+ try {
+ if (resource == null) {
+ handleError("Must define the resource to symlink to!");
+ return;
+ }
+ if (link == null) {
+ handleError("Must define the link name for symlink!");
+ return;
+ }
+ doLink(resource, link);
+ } finally {
+ setDefaults();
+ }
+ }
+
+ /**
+ * Delete a symlink.
+ * @throws BuildException on error.
+ */
+ public void delete() throws BuildException {
try {
- if (action.equals("single")) {
- doLink(resource, link);
- } else if (action.equals("delete")) {
+ if (link == null) {
+ handleError("Must define the link name for symlink!");
+ return;
+ }
+ log("Removing symlink: " + link);
+ deleteSymlink(link);
+ } catch (FileNotFoundException fnfe) {
+ handleError(fnfe.toString());
+ } catch (IOException ioe) {
+ handleError(ioe.toString());
+ } finally {
+ setDefaults();
+ }
+ }
+
+ /**
+ * Restore symlinks.
+ * @throws BuildException on error.
+ */
+ public void recreate() throws BuildException {
+ try {
+ if (fileSets.isEmpty()) {
+ handleError("File set identifying link file(s) "
+ + "required for action recreate");
+ return;
+ }
+ Properties links = loadLinks(fileSets);
+
+ for (Iterator kitr = links.keySet().iterator(); kitr.hasNext();) {
+ String lnk = (String) kitr.next();
+ String res = links.getProperty(lnk);
+ // handle the case where lnk points to a directory (bug 25181)
try {
- log("Removing symlink: " + link);
- Symlink.deleteSymlink(link);
- } catch (FileNotFoundException fnfe) {
- handleError(fnfe.toString());
+ File test = new File(lnk);
+ if (!FILE_UTILS.isSymbolicLink(null, lnk)) {
+ doLink(res, lnk);
+ } else if (!test.getCanonicalPath().equals(
+ new File(res).getCanonicalPath())) {
+ deleteSymlink(lnk);
+ doLink(res, lnk);
+ } // else lnk exists, do nothing
} catch (IOException ioe) {
- handleError(ioe.toString());
+ handleError("IO exception while creating link");
}
- } else if (action.equals("recreate")) {
- Properties listOfLinks;
- Enumeration keys;
-
- if (fileSets.size() == 0) {
- handleError("File set identifying link file(s) "
- + "required for action recreate");
- return;
- }
- listOfLinks = loadLinks(fileSets);
-
- keys = listOfLinks.keys();
+ }
+ } finally {
+ setDefaults();
+ }
+ }
- while (keys.hasMoreElements()) {
- link = (String) keys.nextElement();
- resource = listOfLinks.getProperty(link);
- // handle the case where the link exists
- // and points to a directory (bug 25181)
+ /**
+ * Record symlinks.
+ * @throws BuildException on error.
+ */
+ public void record() throws BuildException {
+ try {
+ if (fileSets.isEmpty()) {
+ handleError("Fileset identifying links to record required");
+ return;
+ }
+ if (linkFileName == null) {
+ handleError("Name of file to record links in required");
+ return;
+ }
+ // create a hashtable to group them by parent directory:
+ Hashtable byDir = new Hashtable();
+
+ // get an Iterator of file objects representing links (canonical):
+ for (Iterator litr = findLinks(fileSets).iterator();
+ litr.hasNext();) {
+ File thisLink = (File) litr.next();
+ File parent = thisLink.getParentFile();
+ Vector v = (Vector) byDir.get(parent);
+ if (v == null) {
+ v = new Vector();
+ byDir.put(parent, v);
+ }
+ v.addElement(thisLink);
+ }
+ // write a Properties file in each directory:
+ for (Iterator dirs = byDir.keySet().iterator(); dirs.hasNext();) {
+ File dir = (File) dirs.next();
+ Vector linksInDir = (Vector) byDir.get(dir);
+ Properties linksToStore = new Properties();
+
+ // fill up a Properties object with link and resource names:
+ for (Iterator dlnk = linksInDir.iterator(); dlnk.hasNext();) {
+ File lnk = (File) dlnk.next();
try {
- File test = new File(link);
- File testRes = new File(resource);
- if (!FILE_UTILS.isSymbolicLink(test.getParentFile(),
- test.getName())) {
- doLink(resource, link);
- } else {
- if (!test.getCanonicalPath().
- equals(testRes.getCanonicalPath())) {
- Symlink.deleteSymlink(link);
- doLink(resource, link);
- } // else the link exists, do nothing
- }
+ linksToStore.put(lnk.getName(), lnk.getCanonicalPath());
} catch (IOException ioe) {
- handleError("IO exception while creating "
- + "link");
+ handleError("Couldn't get canonical name of parent link");
}
}
- } else if (action.equals("record")) {
- Vector vectOfLinks;
- Hashtable byDir = new Hashtable();
- Enumeration links, dirs;
-
- if (fileSets.size() == 0) {
- handleError("Fileset identifying links to "
- + "record required");
- return;
- }
- if (linkFileName == null) {
- handleError("Name of file to record links in "
- + "required");
- return;
- }
- // fill our vector with file objects representing
- // links (canonical)
- vectOfLinks = findLinks(fileSets);
-
- // create a hashtable to group them by parent directory
- links = vectOfLinks.elements();
- while (links.hasMoreElements()) {
- File thisLink = (File) links.nextElement();
- String parent = thisLink.getParent();
- if (byDir.containsKey(parent)) {
- ((Vector) byDir.get(parent)).addElement(thisLink);
- } else {
- byDir.put(parent, new Vector());
- ((Vector) byDir.get(parent)).addElement(thisLink);
- }
- }
- // write a Properties file in each directory
- dirs = byDir.keys();
- while (dirs.hasMoreElements()) {
- String dir = (String) dirs.nextElement();
- Vector linksInDir = (Vector) byDir.get(dir);
- Properties linksToStore = new Properties();
- Enumeration eachlink = linksInDir.elements();
- File writeTo;
-
- // fill up a Properties object with link and resource
- // names
- while (eachlink.hasMoreElements()) {
- File alink = (File) eachlink.nextElement();
- try {
- linksToStore.put(alink.getName(),
- alink.getCanonicalPath());
- } catch (IOException ioe) {
- handleError("Couldn't get canonical "
- + "name of a parent link");
- }
- }
- // Get a place to record what we are about to write
- writeTo = new File(dir + File.separator
- + linkFileName);
-
- writePropertyFile(linksToStore, writeTo,
- "Symlinks from " + writeTo.getParent());
- }
- } else {
- handleError("Invalid action specified in symlink");
+ writePropertyFile(linksToStore, dir);
}
} finally {
- // return all variables to their default state,
- // ready for the next invocation.
- resource = null;
- link = null;
- action = "single";
- fileSets = new Vector();
- linkFileName = null;
- overwrite = false;
- failonerror = true;
+ setDefaults();
}
}
- /* ********************************************************** *
- * Begin Attribute Setter Methods *
- * ********************************************************** */
+ /**
+ * Return all variables to their default state for the next invocation.
+ * @since Ant 1.7
+ */
+ private void setDefaults() {
+ resource = null;
+ link = null;
+ linkFileName = null;
+ failonerror = true; // default behavior is to fail on an error
+ overwrite = false; // default behavior is to not overwrite
+ setAction("single"); // default behavior is make a single link
+ fileSets.clear();
+ }
/**
- * The setter for the overwrite attribute. If set to false (default)
+ * Set overwrite mode. If set to false (default)
* the task will not overwrite existing links, and may stop the build
* if a link already exists depending on the setting of failonerror.
*
@@ -277,29 +303,27 @@
}
/**
- * The setter for the failonerror attribute. If set to true (default)
- * the entire build fails upon error. If set to false, the error is
- * logged and the build will continue.
+ * Set failonerror mode. If set to true (default) the entire build fails
+ * upon error; otherwise the error is logged and the build will continue.
*
- * @param foe If true throw BuildException on error else log it.
+ * @param foe If true throw BuildException on error, else log it.
*/
public void setFailOnError(boolean foe) {
this.failonerror = foe;
}
/**
- * Set the action to be performed. May be
- * "single", "multi" or "record".
+ * Set the action to be performed. May be "single",
+ * "delete", "recreate" or "record".
*
- * @param typ The action to perform.
+ * @param action The action to perform.
*/
- public void setAction(String typ) {
- this.action = typ;
+ public void setAction(String action) {
+ super.setAction(action);
}
/**
- * Set the same of the link.
- * Only used when action = "single".
+ * Set the name of the link. Used when action = "single".
*
* @param lnk The name for the link.
*/
@@ -309,7 +333,7 @@
/**
* Set the name of the resource to which a link should be created.
- * Only used when action = "single".
+ * Used when action = "single".
*
* @param src The resource to be linked.
*/
@@ -319,7 +343,7 @@
/**
* Set the name of the file to which links will be written.
- * Only used when action = "record".
+ * Used when action = "record".
*
* @param lf The name of the file to write links to.
*/
@@ -336,12 +360,8 @@
fileSets.addElement(set);
}
- /* ********************************************************** *
- * Begin Public Utility Methods *
- * ********************************************************** */
-
/**
- * Deletes a symlink without deleting the resource it points to.
+ * Delete a symlink (without deleting the associated resource).
*
* <p>This is a convenience method that simply invokes
* <code>deleteSymlink(java.io.File)</code>.
@@ -359,7 +379,7 @@
}
/**
- * Deletes a symlink without deleting the resource it points to.
+ * Delete a symlink (without deleting the associated resource).
*
* <p>This is a utility method that removes a unix symlink without removing
* the resource that the symlink points to. If it is accidentally invoked
@@ -380,35 +400,28 @@
* <code>File.getCanonicalPath</code>
* fail.
*/
-
- public static void deleteSymlink(File linkfil)
- throws IOException, FileNotFoundException {
-
+ public static void deleteSymlink(File linkfil) throws IOException {
if (!linkfil.exists()) {
throw new FileNotFoundException("No such symlink: " + linkfil);
}
// find the resource of the existing link:
- String canstr = linkfil.getCanonicalPath();
- File canfil = new File(canstr);
+ File canfil = linkfil.getCanonicalFile();
// rename the resource, thus breaking the link:
- String parentStr = canfil.getParent();
- File parentDir = new File(parentStr);
-
- File temp = FILE_UTILS.createTempFile("symlink", ".tmp", parentDir);
- temp.deleteOnExit();
+ File temp = FILE_UTILS.createTempFile("symlink", ".tmp",
+ canfil.getParentFile());
try {
try {
FILE_UTILS.rename(canfil, temp);
} catch (IOException e) {
- throw new IOException("Couldn't rename resource when "
- + "attempting to delete " + linkfil);
+ throw new IOException(
+ "Couldn't rename resource when attempting to delete "
+ + linkfil);
}
// delete the (now) broken link:
if (!linkfil.delete()) {
throw new IOException("Couldn't delete symlink: " + linkfil
- + " (was it a real file? is this not a "
- + "UNIX system?)");
+ + " (was it a real file? is this not a UNIX system?)");
}
} finally {
// return the resource to its original name:
@@ -416,46 +429,36 @@
FILE_UTILS.rename(temp, canfil);
} catch (IOException e) {
throw new IOException("Couldn't return resource " + temp
- + " to its original name: " + canstr
- + "\n THE RESOURCE'S NAME ON DISK HAS "
- + "BEEN CHANGED BY THIS ERROR!\n");
+ + " to its original name: " + canfil.getAbsolutePath()
+ + "\n THE RESOURCE'S NAME ON DISK HAS "
+ + "BEEN CHANGED BY THIS ERROR!\n");
}
}
}
- /* ********************************************************** *
- * Begin Private Methods *
- * ********************************************************** */
-
/**
- * Writes a properties file.
- *
- * This method use <code>Properties.store</code>
- * and thus report exceptions that occur while writing the file.
+ * Write a properties file. This method uses <code>Properties.store</code>
+ * and thus may throw exceptions that occur while writing the file.
*
* @param properties The properties object to be written.
- * @param propertyfile The File to write to.
- * @param comment The comment to place at the head of the file.
+ * @param dir The directory for which we are writing the links.
*/
-
- private void writePropertyFile(Properties properties,
- File propertyfile,
- String comment)
+ private void writePropertyFile(Properties properties, File dir)
throws BuildException {
-
- FileOutputStream fos = null;
+ BufferedOutputStream bos = null;
try {
- fos = new FileOutputStream(propertyfile);
- properties.store(fos, comment);
+ bos = new BufferedOutputStream(
+ new FileOutputStream(new File(dir, linkFileName)));
+ properties.store(bos, "Symlinks from " + dir);
} catch (IOException ioe) {
throw new BuildException(ioe, getLocation());
} finally {
- FILE_UTILS.close(fos);
+ FILE_UTILS.close(bos);
}
}
/**
- * Handles errors correctly based on the setting of failonerror.
+ * Handle errors based on the setting of failonerror.
*
* @param msg The message to log, or include in the
* <code>BuildException</code>.
@@ -468,262 +471,114 @@
}
/**
- * Conducts the actual construction of a link.
+ * Conduct the actual construction of a link.
*
* <p> The link is constructed by calling <code>Execute.runCommand</code>.
*
- * @param resource The path of the resource we are linking to.
- * @param link The name of the link we wish to make.
+ * @param res The path of the resource we are linking to.
+ * @param lnk The name of the link we wish to make.
*/
-
- private void doLink(String resource, String link) throws BuildException {
-
- if (resource == null) {
- handleError("Must define the resource to symlink to!");
- return;
- }
- if (link == null) {
- handleError("Must define the link name for symlink!");
- return;
- }
- File linkfil = new File(link);
-
- String[] cmd = new String[] {"ln", "-s", resource, link};
-
- try {
- if (overwrite && linkfil.exists()) {
+ private void doLink(String res, String lnk) throws BuildException {
+ File linkfil = new File(lnk);
+ if (overwrite && linkfil.exists()) {
+ try {
deleteSymlink(linkfil);
+ } catch (FileNotFoundException fnfe) {
+ handleError("Symlink disappeared before it was deleted: " + lnk);
+ } catch (IOException ioe) {
+ handleError("Unable to overwrite preexisting link: " + lnk);
}
- } catch (FileNotFoundException fnfe) {
- handleError("Symlink disappeared before it was deleted: " + link);
- } catch (IOException ioe) {
- handleError("Unable to overwrite preexisting link: " + link);
}
- log(cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + cmd[3]);
+ String[] cmd = new String[] {"ln", "-s", res, lnk};
+ log(Commandline.toString(cmd));
Execute.runCommand(this, cmd);
}
/**
- * Simultaneously get included directories and included files.
- *
- * @param ds The scanner with which to get the files and directories.
- * @return A vector of <code>String</code> objects containing the
- * included file names and directory names.
- */
- private Vector scanDirsAndFiles(DirectoryScanner ds) {
- String[] files, dirs;
- Vector list = new Vector();
-
- ds.scan();
-
- files = ds.getIncludedFiles();
- dirs = ds.getIncludedDirectories();
-
- for (int i = 0; i < files.length; i++) {
- list.addElement(files[i]);
- }
- for (int i = 0; i < dirs.length; i++) {
- list.addElement(dirs[i]);
- }
- return list;
- }
-
- /**
- * Finds all the links in all supplied filesets.
+ * Find all the links in all supplied filesets.
*
* <p> This method is invoked when the action attribute is
* "record". This means that filesets are interpreted
* as the directories in which links may be found.
*
- * <p> The basic method followed here is, for each fileset:
- * <ol>
- * <li> Compile a list of all matches </li>
- * <li> Convert matches to <code>File</code> objects </li>
- * <li> Remove all non-symlinks using
- * <code>FileUtils.isSymbolicLink</code> </li>
- * <li> Convert all parent directories to the canonical form </li>
- * <li> Add the remaining links from each file set to a
- * master list of links unless the link is already recorded
- * in the list</li>
- * </ol>
- *
- * @param fileSets The filesets specified by the user.
- * @return A Vector of <code>File</code> objects containing the
- * links (with canonical parent directories).
- */
-
- private Vector findLinks(Vector fileSets) {
- Vector result = new Vector();
-
- // loop through the supplied file sets:
- FSLoop: for (int i = 0; i < fileSets.size(); i++) {
- FileSet fsTemp = (FileSet) fileSets.elementAt(i);
- String workingDir = null;
- Vector links = new Vector();
- Vector linksFiles = new Vector();
- Enumeration enumLinks;
-
- DirectoryScanner ds;
-
- File tmpfil = null;
- try {
- tmpfil = fsTemp.getDir(this.getProject());
- workingDir = tmpfil.getCanonicalPath();
- } catch (IOException ioe) {
- handleError("Exception caught getting "
- + "canonical path of working dir " + tmpfil
- + " in a FileSet passed to the symlink "
- + "task. Further processing of this "
- + "fileset skipped");
- continue FSLoop;
- }
- // Get a vector of String with file names that match the pattern:
- ds = fsTemp.getDirectoryScanner(this.getProject());
- links = scanDirsAndFiles(ds);
-
- // Now convert the strings to File Objects
- // using the canonical version of the working dir:
- enumLinks = links.elements();
-
- while (enumLinks.hasMoreElements()) {
- linksFiles.addElement(new File(workingDir
- + File.separator
- + (String) enumLinks
- .nextElement()));
- }
- // Now loop through and remove the non-links:
-
- enumLinks = linksFiles.elements();
-
- File parentNext, next;
- String nameParentNext;
- Vector removals = new Vector();
- while (enumLinks.hasMoreElements()) {
- next = (File) enumLinks.nextElement();
- nameParentNext = next.getParent();
-
- parentNext = new File(nameParentNext);
- try {
- if (!FILE_UTILS.isSymbolicLink(parentNext, next.getName())) {
- removals.addElement(next);
- }
- } catch (IOException ioe) {
- handleError("Failed checking " + next
- + " for symbolic link. FileSet skipped.");
- continue FSLoop;
- // Otherwise this file will be falsely recorded as a link,
- // if failonerror = false, hence the warn and skip.
- }
- }
- enumLinks = removals.elements();
-
- while (enumLinks.hasMoreElements()) {
- linksFiles.removeElement(enumLinks.nextElement());
- }
- // Now we have what we want so add it to results, ensuring that
- // no link is returned twice and we have a canonical reference
- // to the link. (no symlinks in the parent dir)
-
- enumLinks = linksFiles.elements();
- while (enumLinks.hasMoreElements()) {
- File temp, parent;
- next = (File) enumLinks.nextElement();
- try {
- parent = new File(next.getParent());
- parent = new File(parent.getCanonicalPath());
- temp = new File(parent, next.getName());
- if (!result.contains(temp)) {
- result.addElement(temp);
+ * @param v The filesets specified by the user.
+ * @return A HashSet of <code>File</code> objects containing the
+ * links (with canonical parent directories).
+ */
+ private HashSet findLinks(Vector v) {
+ HashSet result = new HashSet();
+ for (int i = 0; i < v.size(); i++) {
+ FileSet fs = (FileSet) v.get(i);
+ DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+ String[][] fnd = new String[][]
+ {ds.getIncludedFiles(), ds.getIncludedDirectories()};
+ File dir = fs.getDir(getProject());
+ for (int j = 0; j < fnd.length; j++) {
+ for (int k = 0; k < fnd[j].length; k++) {
+ try {
+ File f = new File(dir, fnd[j][k]);
+ File pf = f.getParentFile();
+ String name = f.getName();
+ if (FILE_UTILS.isSymbolicLink(pf, name)) {
+ result.add(new File(pf.getCanonicalFile(), name));
+ }
+ } catch (IOException e) {
+ handleError("IOException: " + fnd[j][k] + " omitted");
}
- } catch (IOException ioe) {
- handleError("IOException: " + next + " omitted");
}
}
- // Note that these links are now specified with a full
- // canonical path irrespective of the working dir of the
- // file set so it is ok to mix them in the same vector.
}
return result;
}
/**
- * Load the links from a properties file.
+ * Load links from properties files included in one or more FileSets.
*
* <p> This method is only invoked when the action attribute is set to
- * "multi". The filesets passed in are assumed to specify the
+ * "recreate". The filesets passed in are assumed to specify the
* names of the property files with the link information and the
* subdirectories in which to look for them.
*
- * <p> The basic method follwed here is, for each file set:
- * <ol>
- * <li> Get the canonical version of the dir attribute </li>
- * <li> Scan for properties files </li>
- * <li> load the contents of each properties file found. </li>
- * </ol>
- *
- * @param fileSets The <code>FileSet</code>s for this task
+ * @param v The <code>FileSet</code>s for this task.
* @return The links to be made.
*/
- private Properties loadLinks(Vector fileSets) {
+ private Properties loadLinks(Vector v) {
Properties finalList = new Properties();
- Enumeration keys;
- String key, value;
- String[] includedFiles;
-
// loop through the supplied file sets:
- FSLoop: for (int i = 0; i < fileSets.size(); i++) {
- String workingDir;
- FileSet fsTemp = (FileSet) fileSets.elementAt(i);
-
- DirectoryScanner ds;
-
- try {
- File linelength = fsTemp.getDir(this.getProject());
- workingDir = linelength.getCanonicalPath();
- } catch (IOException ioe) {
- handleError("Exception caught getting "
- + "canonical path of working dir "
- + "of a FileSet passed to symlink "
- + "task. FileSet skipped.");
- continue FSLoop;
- }
- ds = fsTemp.getDirectoryScanner(this.getProject());
+ for (int i = 0; i < v.size(); i++) {
+ FileSet fs = (FileSet) v.elementAt(i);
+ DirectoryScanner ds = fs.getDirectoryScanner(this.getProject());
ds.setFollowSymlinks(false);
ds.scan();
- includedFiles = ds.getIncludedFiles();
-
- // loop through the files identified by each file set
- // and load their contents.
- for (int j = 0; j < includedFiles.length; j++) {
- File inc = new File(workingDir + File.separator
- + includedFiles[j]);
- String inDir;
- Properties propTemp = new Properties();
+ String[] incs = ds.getIncludedFiles();
+ File dir = fs.getDir(getProject());
+ // load included files as properties files:
+ for (int j = 0; j < incs.length; j++) {
+ File inc = new File(dir, incs[j]);
+ File pf = inc.getParentFile();
+ Properties lnks = new Properties();
try {
- propTemp.load(new FileInputStream(inc));
- inDir = inc.getParent();
- inDir = (new File(inDir)).getCanonicalPath();
+ lnks.load(new BufferedInputStream(new FileInputStream(inc)));
+ pf = pf.getCanonicalFile();
} catch (FileNotFoundException fnfe) {
- handleError("Unable to find " + includedFiles[j]
- + "FileSet skipped.");
- continue FSLoop;
+ handleError("Unable to find " + incs[j] + "; skipping it.");
+ continue;
} catch (IOException ioe) {
- handleError("Unable to open " + includedFiles[j]
- + " or its parent dir"
- + "FileSet skipped.");
- continue FSLoop;
+ handleError("Unable to open " + incs[j]
+ + " or its parent dir; skipping it.");
+ continue;
}
- keys = propTemp.keys();
- propTemp.list(System.out);
+ lnks.list(new PrintStream(
+ new LogOutputStream(this, Project.MSG_INFO)));
// Write the contents to our master list of links
// This method assumes that all links are defined in
// terms of absolute paths, or paths relative to the
- // working directory
- while (keys.hasMoreElements()) {
- key = (String) keys.nextElement();
- value = propTemp.getProperty(key);
- finalList.put(inDir + File.separator + key, value);
+ // working directory:
+ for (Iterator kitr = lnks.keySet().iterator(); kitr.hasNext();) {
+ String key = (String) kitr.next();
+ finalList.put(new File(pf, key).getAbsolutePath(),
+ lnks.getProperty(key));
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org