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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]