Methods Summary |
---|
public void | addFileset(org.apache.tools.ant.types.FileSet set)Add a fileset to this task.
fileSets.addElement(set);
|
public void | delete()Delete a symlink.
try {
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();
}
|
public static void | deleteSymlink(java.lang.String path)Delete a symlink (without deleting the associated resource).
This is a convenience method that simply invokes
deleteSymlink(java.io.File) .
deleteSymlink(new File(path));
|
public static void | deleteSymlink(java.io.File linkfil)Delete a symlink (without deleting the associated resource).
This is a utility method that removes a unix symlink without removing
the resource that the symlink points to. If it is accidentally invoked
on a real file, the real file will not be harmed, but an exception
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 its original name inside a finally
block to ensure that the resource is unharmed even in the event of
an exception.
if (!linkfil.exists()) {
throw new FileNotFoundException("No such symlink: " + linkfil);
}
// find the resource of the existing link:
File canfil = linkfil.getCanonicalFile();
// rename the resource, thus breaking the link:
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);
}
// 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:
try {
FILE_UTILS.rename(temp, canfil);
} catch (IOException e) {
throw new IOException("Couldn't return resource " + temp
+ " to its original name: " + canfil.getAbsolutePath()
+ "\n THE RESOURCE'S NAME ON DISK HAS "
+ "BEEN CHANGED BY THIS ERROR!\n");
}
}
|
private void | doLink(java.lang.String res, java.lang.String lnk)Conduct the actual construction of a link.
The link is constructed by calling Execute.runCommand .
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);
}
}
String[] cmd = new String[] {"ln", "-s", res, lnk};
log(Commandline.toString(cmd));
Execute.runCommand(this, cmd);
|
public synchronized void | execute()The standard method for executing any task.
if (executing) {
throw new BuildException(
"Infinite recursion detected in Symlink.execute()");
}
try {
executing = true;
DispatchUtils.execute(this);
} finally {
executing = false;
}
|
private java.util.HashSet | findLinks(java.util.Vector v)Find all the links in all supplied filesets.
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.
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");
}
}
}
}
return result;
|
private void | handleError(java.lang.String msg)Handle errors based on the setting of failonerror.
if (failonerror) {
throw new BuildException(msg);
}
log(msg);
|
public void | init()Initialize the task.
super.init();
setDefaults();
|
private java.util.Properties | loadLinks(java.util.Vector v)Load links from properties files included in one or more FileSets.
This method is only invoked when the action attribute is set to
"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.
Properties finalList = new Properties();
// loop through the supplied file sets:
for (int i = 0; i < v.size(); i++) {
FileSet fs = (FileSet) v.elementAt(i);
DirectoryScanner ds = new DirectoryScanner();
fs.setupDirectoryScanner(ds, getProject());
ds.setFollowSymlinks(false);
ds.scan();
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 {
lnks.load(new BufferedInputStream(new FileInputStream(inc)));
pf = pf.getCanonicalFile();
} catch (FileNotFoundException fnfe) {
handleError("Unable to find " + incs[j] + "; skipping it.");
continue;
} catch (IOException ioe) {
handleError("Unable to open " + incs[j]
+ " or its parent dir; skipping it.");
continue;
}
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:
for (Iterator kitr = lnks.keySet().iterator(); kitr.hasNext();) {
String key = (String) kitr.next();
finalList.put(new File(pf, key).getAbsolutePath(),
lnks.getProperty(key));
}
}
}
return finalList;
|
public void | record()Record symlinks.
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 {
linksToStore.put(lnk.getName(), lnk.getCanonicalPath());
} catch (IOException ioe) {
handleError("Couldn't get canonical name of parent link");
}
}
writePropertyFile(linksToStore, dir);
}
} finally {
setDefaults();
}
|
public void | recreate()Restore symlinks.
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 {
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("IO exception while creating link");
}
}
} finally {
setDefaults();
}
|
public void | setAction(java.lang.String action)Set the action to be performed. May be "single",
"delete", "recreate" or "record".
super.setAction(action);
|
private void | setDefaults()Return all variables to their default state for the next invocation.
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();
|
public void | setFailOnError(boolean foe)Set failonerror mode. If set to true (default) the entire build fails
upon error; otherwise the error is logged and the build will continue.
this.failonerror = foe;
|
public void | setLink(java.lang.String lnk)Set the name of the link. Used when action = "single".
this.link = lnk;
|
public void | setLinkfilename(java.lang.String lf)Set the name of the file to which links will be written.
Used when action = "record".
this.linkFileName = lf;
|
public void | setOverwrite(boolean owrite)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.
this.overwrite = owrite;
|
public void | setResource(java.lang.String src)Set the name of the resource to which a link should be created.
Used when action = "single".
this.resource = src;
|
public void | single()Create a symlink.
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();
}
|
private void | writePropertyFile(java.util.Properties properties, java.io.File dir)Write a properties file. This method uses Properties.store
and thus may throw exceptions that occur while writing the file.
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(
new FileOutputStream(new File(dir, linkFileName)));
properties.store(bos, "Symlinks from " + dir);
} catch (IOException ioe) {
throw new BuildException(ioe, getLocation());
} finally {
FileUtils.close(bos);
}
|