diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java | 600 |
1 files changed, 0 insertions, 600 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java deleted file mode 100644 index ad9aee8b..00000000 --- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * 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 - * Foundaton under Grant No. EIA-0196404. Any opinions, findings, and - * conclusions or recommendations expressed in this material are those - * of the author and do not necessarily reflect the views of the - * National Science Foundation. - */ - -package org.apache.tools.ant.taskdefs.optional.unix; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Properties; -import java.util.Vector; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DirectoryScanner; -import org.apache.tools.ant.Project; -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.util.FileUtils; -import org.apache.tools.ant.util.SymbolicLinkUtils; - -/** - * 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 - * 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 - * (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 associated resource. - * - * <p> Usage examples: - * - * <p> Make a link named "foo" to a resource named - * "bar.foo" in subdir: - * <pre> - * <symlink link="${dir.top}/foo" resource="${dir.top}/subdir/bar.foo"/> - * </pre> - * - * <p> Record all links in subdir and its descendants in files named - * "dir.links": - * <pre> - * <symlink action="record" linkfilename="dir.links"> - * <fileset dir="${dir.top}" includes="subdir/**" /> - * </symlink> - * </pre> - * - * <p> Recreate the links recorded in the previous example: - * <pre> - * <symlink action="recreate"> - * <fileset dir="${dir.top}" includes="subdir/**/dir.links" /> - * </symlink> - * </pre> - * - * <p> Delete a link named "foo" to a resource named - * "bar.foo" in subdir: - * <pre> - * <symlink action="delete" link="${dir.top}/foo"/> - * </pre> - * - * <p><strong>LIMITATIONS:</strong> Because Java has no direct support for - * 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 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 as links to the <strong>canonical</strong> resource name. - * Therefore the link: <code>link --> subdir/dir/../foo.bar</code> will be - * recorded as <code>link=subdir/foo.bar</code> and restored as - * <code>link --> subdir/foo.bar</code>. - * - */ -public class Symlink extends DispatchTask { - private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); - private static final SymbolicLinkUtils SYMLINK_UTILS = - SymbolicLinkUtils.getSymbolicLinkUtils(); - - private String resource; - private String link; - private Vector fileSets = new Vector(); - private String linkFileName; - private boolean overwrite; - private boolean failonerror; - private boolean executing = false; - - /** - * Initialize the task. - * @throws BuildException on error. - */ - @Override - public void init() throws BuildException { - super.init(); - setDefaults(); - } - - /** - * The standard method for executing any task. - * @throws BuildException on error. - */ - @Override - 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. - * @since Ant 1.7 - */ - 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. - * @since Ant 1.7 - */ - public void delete() throws BuildException { - try { - if (link == null) { - handleError("Must define the link name for symlink!"); - return; - } - log("Removing symlink: " + link); - SYMLINK_UTILS.deleteSymbolicLink(FILE_UTILS - .resolveFile(new File("."), link), - this); - } catch (FileNotFoundException fnfe) { - handleError(fnfe.toString()); - } catch (IOException ioe) { - handleError(ioe.toString()); - } finally { - setDefaults(); - } - } - - /** - * Restore symlinks. - * @throws BuildException on error. - * @since Ant 1.7 - */ - 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 { - File test = new File(lnk); - if (!SYMLINK_UTILS.isSymbolicLink(lnk)) { - doLink(res, lnk); - } else if (!test.getCanonicalPath().equals( - new File(res).getCanonicalPath())) { - SYMLINK_UTILS.deleteSymbolicLink(test, this); - doLink(res, lnk); - } // else lnk exists, do nothing - } catch (IOException ioe) { - handleError("IO exception while creating link"); - } - } - } finally { - setDefaults(); - } - } - - /** - * Record symlinks. - * @throws BuildException on error. - * @since Ant 1.7 - */ - 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 { - linksToStore.put(lnk.getName(), lnk.getCanonicalPath()); - } catch (IOException ioe) { - handleError("Couldn't get canonical name of parent link"); - } - } - writePropertyFile(linksToStore, dir); - } - } finally { - setDefaults(); - } - } - - /** - * 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(); - } - - /** - * 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. - * - * @param owrite If true overwrite existing links. - */ - public void setOverwrite(boolean owrite) { - this.overwrite = owrite; - } - - /** - * 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. - */ - public void setFailOnError(boolean foe) { - this.failonerror = foe; - } - - /** - * Set the action to be performed. May be "single", - * "delete", "recreate" or "record". - * - * @param action The action to perform. - */ - @Override - public void setAction(String action) { - super.setAction(action); - } - - /** - * Set the name of the link. Used when action = "single". - * - * @param lnk The name for the link. - */ - public void setLink(String lnk) { - this.link = lnk; - } - - /** - * Set the name of the resource to which a link should be created. - * Used when action = "single". - * - * @param src The resource to be linked. - */ - public void setResource(String src) { - this.resource = src; - } - - /** - * Set the name of the file to which links will be written. - * Used when action = "record". - * - * @param lf The name of the file to write links to. - */ - public void setLinkfilename(String lf) { - this.linkFileName = lf; - } - - /** - * Add a fileset to this task. - * - * @param set The fileset to add. - */ - public void addFileset(FileSet set) { - fileSets.addElement(set); - } - - /** - * Delete a symlink (without deleting the associated resource). - * - * <p>This is a convenience method that simply invokes - * <code>deleteSymlink(java.io.File)</code>. - * - * @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. - * @deprecated use - * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink - * instead - */ - @Deprecated - public static void deleteSymlink(String path) - throws IOException, FileNotFoundException { - SYMLINK_UTILS.deleteSymbolicLink(new File(path), null); - } - - /** - * 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 - * on a real file, the real file will not be harmed.</p> - * - * <p>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.</p> - * - * <p>Since Ant 1.8.0 this method will try to delete the File object if - * it reports it wouldn't exist (as symlinks pointing nowhere usually do). - * Prior version would throw a FileNotFoundException in that case.</p> - * - * @param linkfil A <code>File</code> object of the symlink to delete. - * - * @throws IOException If calls to <code>File.rename</code>, - * <code>File.delete</code> or - * <code>File.getCanonicalPath</code> - * fail. - * @deprecated use - * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink - * instead - */ - @Deprecated - public static void deleteSymlink(File linkfil) - throws IOException { - SYMLINK_UTILS.deleteSymbolicLink(linkfil, null); - } - - /** - * 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 dir The directory for which we are writing the links. - * @throws BuildException if the property file could not be written - */ - private void writePropertyFile(Properties properties, File dir) - throws BuildException { - 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); - } - } - - /** - * Handle errors based on the setting of failonerror. - * - * @param msg The message to log, or include in the - * <code>BuildException</code>. - * @throws BuildException with the message if failonerror=true - */ - private void handleError(String msg) { - if (failonerror) { - throw new BuildException(msg); - } - log(msg); - } - - /** - * Conduct the actual construction of a link. - * - * <p> The link is constructed by calling <code>Execute.runCommand</code>. - * - * @param res The path of the resource we are linking to. - * @param lnk The name of the link we wish to make. - * @throws BuildException when things go wrong - */ - private void doLink(String res, String lnk) throws BuildException { - File linkfil = new File(lnk); - String options = "-s"; - if (overwrite) { - options += "f"; - if (linkfil.exists()) { - try { - SYMLINK_UTILS.deleteSymbolicLink(linkfil, this); - } catch (FileNotFoundException fnfe) { - log("Symlink disappeared before it was deleted: " + lnk); - } catch (IOException ioe) { - log("Unable to overwrite preexisting link or file: " + lnk, - ioe, Project.MSG_INFO); - } - } - } - String[] cmd = new String[] {"ln", options, res, lnk}; - try { - Execute.runCommand(this, cmd); - } catch (BuildException failedToExecute) { - if (failonerror) { - throw failedToExecute; - } else { - //log at the info level, and keep going. - log(failedToExecute.getMessage(), failedToExecute, Project.MSG_INFO); - } - } - } - - /** - * 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. - * - * @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(); - final int size = v.size(); - for (int i = 0; i < 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 (SYMLINK_UTILS.isSymbolicLink(pf, name)) { - result.add(new File(pf.getCanonicalFile(), name)); - } - } catch (IOException e) { - handleError("IOException: " + fnd[j][k] + " omitted"); - } - } - } - } - return result; - } - - /** - * Load links from properties files included in one or more FileSets. - * - * <p> 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. - * - * @param v The <code>FileSet</code>s for this task. - * @return The links to be made. - */ - private Properties loadLinks(Vector v) { - Properties finalList = new Properties(); - // loop through the supplied file sets: - final int size = v.size(); - for (int i = 0; i < 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(); - InputStream is = null; - try { - is = new BufferedInputStream(new FileInputStream(inc)); - lnks.load(is); - 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; - } finally { - FileUtils.close(is); - } - 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; - } -} |