Browse Source

factor out symlink methods into a separate utils class

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@702350 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 16 years ago
parent
commit
9f30d05509
8 changed files with 255 additions and 98 deletions
  1. +8
    -4
      src/main/org/apache/tools/ant/DirectoryScanner.java
  2. +5
    -5
      src/main/org/apache/tools/ant/taskdefs/Delete.java
  3. +9
    -6
      src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
  4. +10
    -1
      src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
  5. +4
    -46
      src/main/org/apache/tools/ant/util/FileUtils.java
  6. +182
    -0
      src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
  7. +2
    -1
      src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java
  8. +35
    -35
      src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java

+ 8
- 4
src/main/org/apache/tools/ant/DirectoryScanner.java View File

@@ -42,6 +42,7 @@ import org.apache.tools.ant.types.selectors.TokenizedPath;
import org.apache.tools.ant.types.selectors.TokenizedPattern;
import org.apache.tools.ant.util.CollectionUtils;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.SymbolicLinkUtils;
import org.apache.tools.ant.util.VectorSet;

/**
@@ -187,6 +188,10 @@ public class DirectoryScanner
/** Helper. */
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

/** Helper. */
private static final SymbolicLinkUtils SYMLINK_UTILS =
SymbolicLinkUtils.getSymbolicLinkUtils();

/**
* Patterns which should be excluded by default.
*
@@ -821,8 +826,7 @@ public class DirectoryScanner
excludes = nullExcludes ? new String[0] : excludes;

if (basedir != null && !followSymlinks
&& FILE_UTILS.isSymbolicLink(basedir.getParentFile(),
basedir.getName())) {
&& SYMLINK_UTILS.isSymbolicLink(basedir)) {
basedir = null;
}

@@ -1178,7 +1182,7 @@ public class DirectoryScanner
ArrayList noLinks = new ArrayList();
for (int i = 0; i < newfiles.length; i++) {
try {
if (FILE_UTILS.isSymbolicLink(dir, newfiles[i])) {
if (SYMLINK_UTILS.isSymbolicLink(dir, newfiles[i])) {
String name = vpath + newfiles[i];
File file = new File(dir, newfiles[i]);
(file.isDirectory()
@@ -1788,7 +1792,7 @@ public class DirectoryScanner
if (directoryNamesFollowed.size() >= maxLevelsOfSymlinks
&& CollectionUtils.frequency(directoryNamesFollowed, dirName)
>= maxLevelsOfSymlinks
&& FILE_UTILS.isSymbolicLink(parent, dirName)) {
&& SYMLINK_UTILS.isSymbolicLink(parent, dirName)) {

ArrayList files = new ArrayList();
File f = FILE_UTILS.resolveFile(parent, dirName);


+ 5
- 5
src/main/org/apache/tools/ant/taskdefs/Delete.java View File

@@ -57,7 +57,7 @@ import org.apache.tools.ant.types.selectors.FilenameSelector;
import org.apache.tools.ant.types.selectors.MajoritySelector;
import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.SymbolicLinkUtils;

/**
* Deletes a file or directory, or set of files defined by a fileset.
@@ -107,14 +107,15 @@ public class Delete extends MatchingTask {
protected boolean usedMatchingTask = false;
// by default, remove matching empty dirs
protected boolean includeEmpty = false;
// CheckStyle:VisibilityModifier ON

private int verbosity = Project.MSG_VERBOSE;
private boolean quiet = false;
private boolean failonerror = true;
private boolean deleteOnExit = false;
private Resources rcs = null;
private static FileUtils FILE_UTILS = FileUtils.getFileUtils();
// CheckStyle:VisibilityModifier ON
private static SymbolicLinkUtils SYMLINK_UTILS =
SymbolicLinkUtils.getSymbolicLinkUtils();

/**
* Set the name of a single file to be removed.
@@ -760,8 +761,7 @@ public class Delete extends MatchingTask {

private boolean isDanglingSymlink(File f) {
try {
return FILE_UTILS.isDanglingSymbolicLink(f.getParentFile(),
f.getName());
return SYMLINK_UTILS.isDanglingSymbolicLink(f);
} catch (java.io.IOException e) {
log("Error while trying to detect " + f.getAbsolutePath()
+ " as broken symbolic link. " + e.getMessage(),


+ 9
- 6
src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java View File

@@ -54,6 +54,7 @@ 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.
@@ -114,6 +115,8 @@ import org.apache.tools.ant.util.FileUtils;
*/
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;
@@ -212,7 +215,7 @@ public class Symlink extends DispatchTask {
// handle the case where lnk points to a directory (bug 25181)
try {
File test = new File(lnk);
if (!FILE_UTILS.isSymbolicLink(null, lnk)) {
if (!SYMLINK_UTILS.isSymbolicLink(lnk)) {
doLink(res, lnk);
} else if (!test.getCanonicalPath().equals(
new File(res).getCanonicalPath())) {
@@ -466,14 +469,14 @@ public class Symlink extends DispatchTask {
*/
public static void deleteSymlink(File linkfil, Task task)
throws IOException {
if (FILE_UTILS.isDanglingSymbolicLink(linkfil.getParentFile(),
linkfil.getName())) {
if (SYMLINK_UTILS.isDanglingSymbolicLink(linkfil.getParentFile(),
linkfil.getName())) {
linkfil.delete();
return;
}

if (!FILE_UTILS.isSymbolicLink(linkfil.getParentFile(),
linkfil.getName())) {
if (!SYMLINK_UTILS.isSymbolicLink(linkfil.getParentFile(),
linkfil.getName())) {
// plain file, not a link
return;
}
@@ -641,7 +644,7 @@ public class Symlink extends DispatchTask {
File f = new File(dir, fnd[j][k]);
File pf = f.getParentFile();
String name = f.getName();
if (FILE_UTILS.isSymbolicLink(pf, name)) {
if (SYMLINK_UTILS.isSymbolicLink(pf, name)) {
result.add(new File(pf.getCanonicalFile(), name));
}
} catch (IOException e) {


+ 10
- 1
src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java View File

@@ -22,6 +22,7 @@ import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.SymbolicLinkUtils;

/**
* Container for a path that has been split into its components.
@@ -37,6 +38,9 @@ public class TokenizedPath {

/** Helper. */
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/** Helper. */
private static final SymbolicLinkUtils SYMLINK_UTILS =
SymbolicLinkUtils.getSymbolicLinkUtils();
/** iterations for case-sensitive scanning. */
private static final boolean[] CS_SCAN_ONLY = new boolean[] {true};
/** iterations for non-case-sensitive scanning. */
@@ -134,7 +138,12 @@ public class TokenizedPath {
public boolean isSymlink(File base) {
for (int i = 0; i < tokenizedPath.length; i++) {
try {
if (FILE_UTILS.isSymbolicLink(base, tokenizedPath[i])) {
if ((base != null
&& SYMLINK_UTILS.isSymbolicLink(base, tokenizedPath[i]))
||
(base == null
&& SYMLINK_UTILS.isSymbolicLink(tokenizedPath[i]))
) {
return true;
}
base = new File(base, tokenizedPath[i]);


+ 4
- 46
src/main/org/apache/tools/ant/util/FileUtils.java View File

@@ -1039,57 +1039,15 @@ public class FileUtils {
* @return true if the file is a symbolic link.
* @throws IOException on error.
* @since Ant 1.5
* @deprecated use SymbolicLinkUtils instead
*/
public boolean isSymbolicLink(File parent, String name)
throws IOException {
SymbolicLinkUtils u = SymbolicLinkUtils.getSymbolicLinkUtils();
if (parent == null) {
File f = new File(name);
parent = f.getParentFile();
name = f.getName();
return u.isSymbolicLink(name);
}
File toTest = new File(parent.getCanonicalPath(), name);
return !toTest.getAbsolutePath().equals(toTest.getCanonicalPath());
}

/**
* Checks whether a given file is a broken symbolic link.
*
* <p>It doesn't really test for symbolic links but whether Java
* reports that the File doesn't exist but its parent's child list
* contains it--this may lead to false positives on some
* platforms.</p>
*
* <p>Note that #isSymbolicLink returns false if this method
* returns true since Java won't produce a canonical name
* different from the abolute one if the link is broken.</p>
*
* @param parent the parent directory of the file to test
* @param name the name of the file to test.
*
* @return true if the file is a broken symbolic link.
* @throws IOException on error.
* @since Ant 1.8.0
*/
public boolean isDanglingSymbolicLink(File parent, String name)
throws IOException {
File f = null;
if (parent == null) {
f = new File(name);
parent = f.getParentFile();
name = f.getName();
} else {
f = new File(parent, name);
}
if (!f.exists()) {
final String localName = f.getName();
String[] c = parent.list(new FilenameFilter() {
public boolean accept(File d, String n) {
return localName.equals(n);
}
});
return c != null && c.length > 0;
}
return false;
return u.isSymbolicLink(parent, name);
}

/**


+ 182
- 0
src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java View File

@@ -0,0 +1,182 @@
/*
* 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.
*
*/
package org.apache.tools.ant.util;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

/**
* Contains methods related to symbolic links - or what Ant thinks is
* a symbolic link based on the absent support for them in Java.
*
* @since Ant 1.8.0
*/
public class SymbolicLinkUtils {
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

/**
* Shared instance.
*/
private static final SymbolicLinkUtils PRIMARY_INSTANCE =
new SymbolicLinkUtils();

/**
* Method to retrieve The SymbolicLinkUtils, which is shared by
* all users of this method.
* @return an instance of SymbolicLinkUtils.
*/
public static SymbolicLinkUtils getSymbolicLinkUtils() {
// keep the door open for Java X.Y specific subclass if symbolic
// links ever become supported in the classlib
return PRIMARY_INSTANCE;
}

/**
* Empty constructor.
*/
protected SymbolicLinkUtils() {
}

/**
* Checks whether a given file is a symbolic link.
*
* <p>It doesn't really test for symbolic links but whether the
* canonical and absolute paths of the file are identical--this
* may lead to false positives on some platforms.</p>
*
* @param file the file to test.
*
* @return true if the file is a symbolic link.
* @throws IOException on error.
*/
public boolean isSymbolicLink(File file) throws IOException {
return isSymbolicLink(file.getParentFile(), file.getName());
}

/**
* Checks whether a given file is a symbolic link.
*
* <p>It doesn't really test for symbolic links but whether the
* canonical and absolute paths of the file are identical--this
* may lead to false positives on some platforms.</p>
*
* @param name the name of the file to test.
*
* @return true if the file is a symbolic link.
* @throws IOException on error.
*/
public boolean isSymbolicLink(String name) throws IOException {
return isSymbolicLink(new File(name));
}

/**
* Checks whether a given file is a symbolic link.
*
* <p>It doesn't really test for symbolic links but whether the
* canonical and absolute paths of the file are identical--this
* may lead to false positives on some platforms.</p>
*
* @param parent the parent directory of the file to test
* @param name the name of the file to test.
*
* @return true if the file is a symbolic link.
* @throws IOException on error.
*/
public boolean isSymbolicLink(File parent, String name)
throws IOException {
File toTest = new File(parent.getCanonicalPath(), name);
return !toTest.getAbsolutePath().equals(toTest.getCanonicalPath());
}

/**
* Checks whether a given file is a broken symbolic link.
*
* <p>It doesn't really test for symbolic links but whether Java
* reports that the File doesn't exist but its parent's child list
* contains it--this may lead to false positives on some
* platforms.</p>
*
* <p>Note that #isSymbolicLink returns false if this method
* returns true since Java won't produce a canonical name
* different from the abolute one if the link is broken.</p>
*
* @param name the name of the file to test.
*
* @return true if the file is a broken symbolic link.
* @throws IOException on error.
*/
public boolean isDanglingSymbolicLink(String name) throws IOException {
return isDanglingSymbolicLink(new File(name));
}

/**
* Checks whether a given file is a broken symbolic link.
*
* <p>It doesn't really test for symbolic links but whether Java
* reports that the File doesn't exist but its parent's child list
* contains it--this may lead to false positives on some
* platforms.</p>
*
* <p>Note that #isSymbolicLink returns false if this method
* returns true since Java won't produce a canonical name
* different from the abolute one if the link is broken.</p>
*
* @param file the file to test.
*
* @return true if the file is a broken symbolic link.
* @throws IOException on error.
*/
public boolean isDanglingSymbolicLink(File file) throws IOException {
return isDanglingSymbolicLink(file.getParentFile(), file.getName());
}

/**
* Checks whether a given file is a broken symbolic link.
*
* <p>It doesn't really test for symbolic links but whether Java
* reports that the File doesn't exist but its parent's child list
* contains it--this may lead to false positives on some
* platforms.</p>
*
* <p>Note that #isSymbolicLink returns false if this method
* returns true since Java won't produce a canonical name
* different from the abolute one if the link is broken.</p>
*
* @param parent the parent directory of the file to test
* @param name the name of the file to test.
*
* @return true if the file is a broken symbolic link.
* @throws IOException on error.
*/
public boolean isDanglingSymbolicLink(File parent, String name)
throws IOException {
File f = new File(parent, name);
if (!f.exists()) {
final String localName = f.getName();
String[] c = parent.list(new FilenameFilter() {
public boolean accept(File d, String n) {
return localName.equals(n);
}
});
return c != null && c.length > 0;
}
return false;
}

}

+ 2
- 1
src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java View File

@@ -20,6 +20,7 @@ package org.apache.tools.ant;

import org.apache.tools.ant.taskdefs.condition.Os;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.SymbolicLinkUtils;


import java.io.File;
@@ -247,7 +248,7 @@ public class DirectoryScannerTest extends BuildFileTest {

File dir = new File(System.getProperty("root"), "src/main/org/apache/tools");
System.err.println("link exists after exec? " + linkFile.exists());
System.err.println("Ant knows it is a link? " + FileUtils.getFileUtils().isSymbolicLink(dir, "ThisIsALink"));
System.err.println("Ant knows it is a link? " + SymbolicLinkUtils.getSymbolicLinkUtils().isSymbolicLink(dir, "ThisIsALink"));

DirectoryScanner ds = new DirectoryScanner();



+ 35
- 35
src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java View File

@@ -33,7 +33,7 @@ import org.apache.tools.ant.taskdefs.condition.Os;

import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.SymbolicLinkUtils;

/**
* Test cases for the Symlink task. Link creation, link deletion, recording
@@ -182,53 +182,53 @@ public class SymlinkTest extends BuildFileTest {
}
}

public void testFileUtilsMethods() throws Exception {
public void testSymbolicLinkUtilsMethods() throws Exception {
if (supportsSymlinks) {
executeTarget("test-fileutils");
FileUtils fu = FileUtils.getFileUtils();
SymbolicLinkUtils su = SymbolicLinkUtils.getSymbolicLinkUtils();

java.io.File f = getProject().resolveFile("test-working/file1");
assertTrue(f.exists());
assertFalse(f.isDirectory());
assertTrue(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/dir1");
assertTrue(f.exists());
assertTrue(f.isDirectory());
assertFalse(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/file2");
assertFalse(f.exists());
assertFalse(f.isDirectory());
assertFalse(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/dir2");
assertFalse(f.exists());
assertFalse(f.isDirectory());
assertFalse(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));


@@ -236,44 +236,44 @@ public class SymlinkTest extends BuildFileTest {
assertTrue(f.exists());
assertFalse(f.isDirectory());
assertTrue(f.isFile());
assertTrue(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertTrue(fu.isSymbolicLink(f.getParentFile(),
assertTrue(su.isSymbolicLink(f.getAbsolutePath()));
assertTrue(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/dir.there");
assertTrue(f.exists());
assertTrue(f.isDirectory());
assertFalse(f.isFile());
assertTrue(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertTrue(fu.isSymbolicLink(f.getParentFile(),
assertTrue(su.isSymbolicLink(f.getAbsolutePath()));
assertTrue(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
assertFalse(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/file.notthere");
assertFalse(f.exists());
assertFalse(f.isDirectory());
assertFalse(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertTrue(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertTrue(fu.isDanglingSymbolicLink(f.getParentFile(),
assertTrue(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertTrue(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

f = getProject().resolveFile("test-working/dir.notthere");
assertFalse(f.exists());
assertFalse(f.isDirectory());
assertFalse(f.isFile());
assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
assertFalse(fu.isSymbolicLink(f.getParentFile(),
assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
assertFalse(su.isSymbolicLink(f.getParentFile(),
f.getName()));
assertTrue(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
assertTrue(fu.isDanglingSymbolicLink(f.getParentFile(),
assertTrue(su.isDanglingSymbolicLink(f.getAbsolutePath()));
assertTrue(su.isDanglingSymbolicLink(f.getParentFile(),
f.getName()));

}


Loading…
Cancel
Save