mbenson 2005/01/27 15:48:32
Modified: src/main/org/apache/tools/ant/taskdefs/optional/unix Tag:
ANT_16_BRANCH Symlink.java
Log:
Merge
Revision Changes Path
No revision
No revision
1.12.2.7 +80 -120
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.12.2.6
retrieving revision 1.12.2.7
diff -u -r1.12.2.6 -r1.12.2.7
--- Symlink.java 7 Jun 2004 12:03:55 -0000 1.12.2.6
+++ Symlink.java 27 Jan 2005 23:48:32 -0000 1.12.2.7
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2004 The Apache Software Foundation
+ * Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
*/
/*
- * Since the initial version of this file was deveolped on the clock on
+ * Since the initial version of this file was developed on the clock on
* an NSF grant I should say the following boilerplate:
*
* This material is based upon work supported by the National Science
@@ -52,10 +52,10 @@
/**
* Creates, 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 atribute to
- * a resource specified in the resource atribute. The second usage of this
- * task is to traverses a directory structure specified by a fileset,
+ * <p> This task performs several related operations. In the most trivial
+ * and default usage, it creates a link specified in the link attribute to
+ * a resource specified in the resource attribute. The second usage of this
+ * task is to traverse a directory structure specified by a fileset,
* and write a properties file in each included directory describing the
* links found in that directory. The third usage is to traverse a
* directory structure specified by a fileset, looking for properties files
@@ -92,10 +92,10 @@
* </pre>
*
* <p><strong>LIMITATIONS:</strong> Because Java has no direct support for
- * handling symlinks this task divines them by comparing canoniacal and
+ * handling symlinks this task divines them by comparing canonical and
* 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 comandline
+ * <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" or
* action="recreate", but action="record" should still work. Finally, the
* lack of support for symlinks in Java means that all links are recorded
@@ -109,7 +109,7 @@
public class Symlink extends Task {
- // Atributes with setter methods
+ // Attributes with setter methods:
private String resource;
private String link;
private String action;
@@ -118,18 +118,22 @@
private boolean overwrite;
private boolean failonerror;
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
/** Initialize the task. */
public void init() throws BuildException {
super.init();
failonerror = true; // default behavior is to fail on an error
- overwrite = false; // devault behavior is to not overwrite
+ overwrite = false; // default behavior is to not overwrite
action = "single"; // default behavior is make a single link
fileSets = new Vector();
}
- /** The standard method for executing any task. */
-
+ /**
+ * The standard method for executing any task.
+ * @throws BuildException on error.
+ */
public void execute() throws BuildException {
try {
if (action.equals("single")) {
@@ -152,7 +156,6 @@
+ "required for action recreate");
return;
}
-
listOfLinks = loadLinks(fileSets);
keys = listOfLinks.keys();
@@ -160,26 +163,25 @@
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)
- try {
- FileUtils fu = FileUtils.newFileUtils();
- File test = new File(link);
- File testRes = new File(resource);
- if (!fu.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
- }
- } catch (IOException ioe) {
- handleError("IO exception while creating "
- + "link");
- }
+ // handle the case where the link exists
+ // and points to a directory (bug 25181)
+ 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
+ }
+ } catch (IOException ioe) {
+ handleError("IO exception while creating "
+ + "link");
+ }
}
} else if (action.equals("record")) {
Vector vectOfLinks;
@@ -187,17 +189,15 @@
Enumeration links, dirs;
if (fileSets.size() == 0) {
- handleError("File set identifying links to "
+ 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);
@@ -214,7 +214,6 @@
((Vector) byDir.get(parent)).addElement(thisLink);
}
}
-
// write a Properties file in each directory
dirs = byDir.keys();
while (dirs.hasMoreElements()) {
@@ -236,8 +235,6 @@
+ "name of a parent link");
}
}
-
-
// Get a place to record what we are about to write
writeTo = new File(dir + File.separator
+ linkFileName);
@@ -262,11 +259,11 @@
}
/* ********************************************************** *
- * Begin Atribute Setter Methods *
+ * Begin Attribute Setter Methods *
* ********************************************************** */
/**
- * The setter for the overwrite atribute. If set to false (default)
+ * The setter for the overwrite attribute. 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,22 +274,21 @@
}
/**
- * The setter for the failonerror atribute. If set to true (default)
+ * 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.
*
- * @param foe If true throw build exception on error else log it.
+ * @param foe If true throw BuildException on error else log it.
*/
public void setFailOnError(boolean foe) {
this.failonerror = foe;
}
-
/**
- * The setter for the "action" attribute. May be "single" "multi"
+ * The setter for the "action" attribute. May be "single", "multi"
* or "record"
*
- * @param typ The action of action to perform
+ * @param typ The action of action to perform.
*/
public void setAction(String typ) {
this.action = typ;
@@ -301,7 +297,7 @@
/**
* The setter for the "link" attribute. Only used for action = single.
*
- * @param lnk The name for the link
+ * @param lnk The name for the link.
*/
public void setLink(String lnk) {
this.link = lnk;
@@ -335,32 +331,29 @@
}
/* ********************************************************** *
- * Begin Public Utility Methods *
+ * Begin Public Utility Methods *
* ********************************************************** */
/**
* Deletes a symlink without deleteing the resource it points to.
*
* <p>This is a convenience method that simply invokes
- * <code>deleteSymlink(java.io.File)</code>
+ * <code>deleteSymlink(java.io.File)</code>.
*
- * @param path A string containing the path of the symlink to delete
+ * @param path A string containing the path of the symlink to delete.
*
* @throws FileNotFoundException When the path results in a
* <code>File</code> that doesn't
exist.
* @throws IOException If calls to <code>File.rename</code>
* or <code>File.delete</code> fail.
*/
-
public static void deleteSymlink(String path)
throws IOException, FileNotFoundException {
-
- File linkfil = new File(path);
- deleteSymlink(linkfil);
+ deleteSymlink(new File(path));
}
/**
- * Deletes a symlink without deleteing the resource it points to.
+ * Deletes a symlink without deleting the resource it points to.
*
* <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
@@ -368,11 +361,11 @@
* will be thrown when the deletion is attempted. This method works by
* getting the canonical path of the link, using the canonical path to
* rename the resource (breaking the link) and then deleting the link.
- * The resource is then returned to it's original name inside a finally
+ * The resource is then returned to its original name inside a finally
* block to ensure that the resource is unharmed even in the event of
* an exception.
*
- * @param linkfil A <code>File</code> object of the symlink to delete
+ * @param linkfil A <code>File</code> object of the symlink to delete.
*
* @throws FileNotFoundException When the path results in a
* <code>File</code> that doesn't
exist.
@@ -388,35 +381,33 @@
if (!linkfil.exists()) {
throw new FileNotFoundException("No such symlink: " + linkfil);
}
-
- // find the resource of the existing link
+ // find the resource of the existing link:
String canstr = linkfil.getCanonicalPath();
File canfil = new File(canstr);
- // rename the resource, thus breaking the link
+ // rename the resource, thus breaking the link:
String parentStr = canfil.getParent();
File parentDir = new File(parentStr);
- FileUtils fu = FileUtils.newFileUtils();
- File temp = fu.createTempFile("symlink", ".tmp", parentDir);
+
+ File temp = FILE_UTILS.createTempFile("symlink", ".tmp", parentDir);
temp.deleteOnExit();
try {
try {
- fu.rename(canfil, temp);
+ FILE_UTILS.rename(canfil, temp);
} catch (IOException e) {
throw new IOException("Couldn't rename resource when "
+ "attempting to delete " + linkfil);
}
-
- // delete the (now) broken link
+ // 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?)");
}
} finally {
- // return the resource to its original name.
+ // return the resource to its original name:
try {
- fu.rename(temp, canfil);
+ FILE_UTILS.rename(temp, canfil);
} catch (IOException e) {
throw new IOException("Couldn't return resource " + temp
+ " to its original name: " + canstr
@@ -426,9 +417,8 @@
}
}
-
/* ********************************************************** *
- * Begin Private Methods *
+ * Begin Private Methods *
* ********************************************************** */
/**
@@ -437,7 +427,7 @@
* This method use <code>Properties.store</code>
* and thus report exceptions that occur while writing the file.
*
- * This is not jdk 1.1 compatible, but ant 1.6 is not anymore.
+ * This is not jdk 1.1 compatible, but Ant 1.6 is not anymore.
*
* @param properties The properties object to be written.
* @param propertyfile The File to write to.
@@ -457,13 +447,7 @@
} catch (IOException ioe) {
throw new BuildException(ioe, getLocation());
} finally {
- if (fos != null) {
- try {
- fos.close();
- } catch (IOException ioex) {
- log("Failed to close output stream");
- }
- }
+ FILE_UTILS.close(fos);
}
}
@@ -471,25 +455,22 @@
* Handles errors correctly based on the setting of failonerror.
*
* @param msg The message to log, or include in the
- * <code>BuildException</code>
+ * <code>BuildException</code>.
*/
-
private void handleError(String msg) {
if (failonerror) {
throw new BuildException(msg);
- } else {
- log(msg);
}
+ log(msg);
}
-
/**
* Conducts 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 link The name of the link we wish to make.
*/
private void doLink(String resource, String link) throws BuildException {
@@ -499,34 +480,26 @@
return;
}
if (link == null) {
- handleError("Must define the link "
- + "name for symlink!");
+ handleError("Must define the link name for symlink!");
return;
}
-
File linkfil = new File(link);
- String[] cmd = new String[4];
- cmd[0] = "ln";
- cmd[1] = "-s";
- cmd[2] = resource;
- cmd[3] = link;
+ String[] cmd = new String[] {"ln", "-s", resource, link};
try {
if (overwrite && linkfil.exists()) {
deleteSymlink(linkfil);
}
} catch (FileNotFoundException fnfe) {
- handleError("Symlink dissapeared before it was deleted:" + link);
+ handleError("Symlink disappeared before it was deleted: " +
link);
} catch (IOException ioe) {
- handleError("Unable to overwrite preexisting link " + link);
+ handleError("Unable to overwrite preexisting link: " + link);
}
-
log(cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + cmd[3]);
Execute.runCommand(this, cmd);
}
-
/**
* Simultaneously get included directories and included files.
*
@@ -534,7 +507,6 @@
* @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();
@@ -550,14 +522,13 @@
for (int i = 0; i < dirs.length; i++) {
list.addElement(dirs[i]);
}
-
return list;
}
/**
* Finds all the links in all supplied filesets.
*
- * <p> This method is invoked when the action atribute is is "record".
+ * <p> This method is invoked when the action attribute is is "record".
* This means that filesets are interpreted as the directories in
* which links may be found.
*
@@ -575,13 +546,13 @@
*
* @param fileSets The filesets specified by the user.
* @return A vector of <code>File</code> objects containing the
- * links (with canonical parent directories)
+ * links (with canonical parent directories).
*/
private Vector findLinks(Vector fileSets) {
Vector result = new Vector();
- // loop through the supplied file sets
+ // loop through the supplied file sets:
FSLoop: for (int i = 0; i < fileSets.size(); i++) {
FileSet fsTemp = (FileSet) fileSets.elementAt(i);
String workingDir = null;
@@ -603,14 +574,12 @@
+ "fileset skipped");
continue FSLoop;
}
-
- // Get a vector of String with file names that match
- // the pattern
+ // 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
+ // using the canonical version of the working dir:
enumLinks = links.elements();
while (enumLinks.hasMoreElements()) {
@@ -619,14 +588,12 @@
+ (String) enumLinks
.nextElement()));
}
-
- // Now loop through and remove the non-links
+ // Now loop through and remove the non-links:
enumLinks = linksFiles.elements();
File parentNext, next;
String nameParentNext;
- FileUtils fu = FileUtils.newFileUtils();
Vector removals = new Vector();
while (enumLinks.hasMoreElements()) {
next = (File) enumLinks.nextElement();
@@ -634,7 +601,7 @@
parentNext = new File(nameParentNext);
try {
- if (!fu.isSymbolicLink(parentNext, next.getName())) {
+ if (!FILE_UTILS.isSymbolicLink(parentNext,
next.getName())) {
removals.addElement(next);
}
} catch (IOException ioe) {
@@ -645,13 +612,11 @@
// 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)
@@ -671,11 +636,9 @@
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;
}
@@ -683,14 +646,14 @@
/**
* Load the links from a properties file.
*
- * <p> This method is only invoked when the action atribute is set to
+ * <p> This method is only invoked when the action attribute is set to
* "multi". 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 atribute </li>
+ * <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>
@@ -698,14 +661,13 @@
* @param fileSets The <code>FileSet</code>s for this task
* @return The links to be made.
*/
-
private Properties loadLinks(Vector fileSets) {
Properties finalList = new Properties();
Enumeration keys;
String key, value;
String[] includedFiles;
- // loop through the supplied file sets
+ // loop through the supplied file sets:
FSLoop: for (int i = 0; i < fileSets.size(); i++) {
String workingDir;
FileSet fsTemp = (FileSet) fileSets.elementAt(i);
@@ -722,7 +684,6 @@
+ "task. FileSet skipped.");
continue FSLoop;
}
-
ds = fsTemp.getDirectoryScanner(this.getProject());
ds.setFollowSymlinks(false);
ds.scan();
@@ -746,11 +707,10 @@
continue FSLoop;
} catch (IOException ioe) {
handleError("Unable to open " + includedFiles[j]
- + " or it's parent dir"
+ + " or its parent dir"
+ "FileSet skipped.");
continue FSLoop;
}
-
keys = propTemp.keys();
propTemp.list(System.out);
// Write the contents to our master list of links
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]