You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2014/10/13 20:42:21 UTC

svn commit: r1631506 - in /maven/shared/trunk/maven-shared-utils/src: main/java/org/apache/maven/shared/utils/io/ test/java/org/apache/maven/shared/utils/io/

Author: krosenvold
Date: Mon Oct 13 18:42:21 2014
New Revision: 1631506

URL: http://svn.apache.org/r1631506
Log:
Added symbolic link detection logic and java7 symlink methods with reflection

Modified:
    maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java
    maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/Java7Support.java
    maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/FileUtilsTest.java
    maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/Java7SupportTest.java

Modified: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java?rev=1631506&r1=1631505&r2=1631506&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java Mon Oct 13 18:42:21 2014
@@ -1988,4 +1988,67 @@ public class FileUtils
 
         return true;
     }
+
+    /**
+     * Checks whether a given file is a symbolic link.
+     *
+     * This only works reliably on java7 and higher. For earlier version we use a highly crappy heuristic
+     * that mostly does not work.
+     * <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 check
+     *
+     */
+    public static boolean isSymbolicLink( final File file )
+        throws IOException
+    {
+        if ( Java7Support.isJava7() )
+        {
+            return Java7Support.isSymLink( file );
+        }
+        return isSymbolicLinkLegacy( file );
+    }
+
+    /**
+     * Checks whether a given file is a symbolic link.
+     *
+     * @param file the file to check
+     * @return true if and only if we reliably can say this is a symlink. This will
+     *         always return false for java versions prior to 1.7.
+     *
+     */
+    public static boolean isSymbolicLinkForSure( final File file )
+        throws IOException
+    {
+        return Java7Support.isJava7() && Java7Support.isSymLink( file );
+    }
+
+    /**
+     * 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.
+     *
+     * It also returns true for any file that has been reached via a symbolic link,
+     * if you decide to traverse into the symlink.
+     *
+     * As can be seen from the "return" clause of this method, there is really no
+     * guarantee of any sort from this method. Small wonder this ever got used for
+     * anything.
+     * </p>
+     *
+     * @param file the file to check
+     * @return true if the file is a symbolic link or if we're on some crappy os.
+     *         false if the file is not a symlink or we're not able to detect it.
+     */
+    static boolean isSymbolicLinkLegacy( final File file )
+        throws IOException
+    {
+        final File canonical = new File( file.getCanonicalPath() );
+        return !file.getAbsolutePath().equals( canonical.getPath() );
+    }
+
 }

Modified: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/Java7Support.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/Java7Support.java?rev=1631506&r1=1631505&r2=1631506&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/Java7Support.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/Java7Support.java Mon Oct 13 18:42:21 2014
@@ -19,10 +19,18 @@ package org.apache.maven.shared.utils.io
  * under the License.
  */
 
+import com.sun.org.apache.xalan.internal.xsltc.compiler.sym;
+
+import javax.annotation.Nonnull;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileAttribute;
 
 /**
  * Java7 feature detection
@@ -40,6 +48,18 @@ public class Java7Support
 
     private static Method toPath;
 
+    private static Method exists;
+
+    private static Method toFile;
+
+    private static Method readSymlink;
+
+    private static Method createSymlink;
+
+    private static Object emptyLinkOpts;
+
+    private static Object emptyFileAttributes;
+
     static
     {
         boolean isJava7x = true;
@@ -47,9 +67,19 @@ public class Java7Support
         {
             Class<?> files = Thread.currentThread().getContextClassLoader().loadClass( "java.nio.file.Files" );
             Class<?> path = Thread.currentThread().getContextClassLoader().loadClass( "java.nio.file.Path" );
+            Class<?> fa = Thread.currentThread().getContextClassLoader().loadClass( "java.nio.file.attribute.FileAttribute" );
+            Class<?> linkOption = Thread.currentThread().getContextClassLoader().loadClass( "java.nio.file.LinkOption" );
             isSymbolicLink = files.getMethod( "isSymbolicLink", path );
             delete = files.getMethod( "delete", path );
+            readSymlink = files.getMethod( "readSymbolicLink", path );
+
+            emptyFileAttributes = Array.newInstance( fa, 0 );
+            final Object o = emptyFileAttributes;
+            createSymlink  = files.getMethod( "createSymbolicLink", path,path, o.getClass() );
+            emptyLinkOpts = Array.newInstance( linkOption, 0 );
+            exists = files.getMethod( "exists", path, emptyLinkOpts.getClass() );
             toPath = File.class.getMethod( "toPath" );
+            toFile = path.getMethod( "toFile" );
         }
         catch ( ClassNotFoundException e )
         {
@@ -62,7 +92,7 @@ public class Java7Support
         IS_JAVA7 = isJava7x;
     }
 
-    public static boolean isSymLink( File file )
+    public static boolean isSymLink( @Nonnull File file )
     {
         try
         {
@@ -79,6 +109,70 @@ public class Java7Support
         }
     }
 
+
+    public static @Nonnull File readSymbolicLink( @Nonnull File symlink )
+        throws IOException
+    {
+        try
+        {
+            Object path = toPath.invoke( symlink );
+            Object resultPath =  readSymlink.invoke( null, path );
+            return (File) toFile.invoke( resultPath );
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public static boolean exists( @Nonnull File file )
+        throws IOException
+    {
+        try
+        {
+            Object path = toPath.invoke( file );
+            final Object invoke = exists.invoke( null, path, emptyLinkOpts );
+            return ((Boolean)invoke).booleanValue();
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw (RuntimeException) e.getTargetException();
+        }
+
+    }
+
+    public static @Nonnull File createSymbolicLink( @Nonnull File symlink,  @Nonnull File target )
+        throws IOException
+    {
+        try
+        {
+            if (!exists( symlink )){
+                Object link = toPath.invoke( symlink );
+                Object path = createSymlink.invoke( null, link, toPath.invoke( target ), emptyFileAttributes );
+                return (File) toFile.invoke( path );
+            }
+            return symlink;
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            final Throwable targetException = e.getTargetException();
+            throw (IOException)targetException;
+        }
+
+    }
     /**
      * Performs a nio delete
      * @param file the file to delete

Modified: maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/FileUtilsTest.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/FileUtilsTest.java?rev=1631506&r1=1631505&r2=1631506&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/FileUtilsTest.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/FileUtilsTest.java Mon Oct 13 18:42:21 2014
@@ -1368,6 +1368,24 @@ public class FileUtilsTest
     }
 
     @Test
+    public void isASymbolicLink()
+        throws IOException
+    {
+        File file = new File( "src/test/resources/symlinks/src/symDir" );
+        assertTrue(FileUtils.isSymbolicLink(file  ));
+        assertTrue(FileUtils.isSymbolicLinkLegacy(file  ));
+    }
+
+    @Test
+    public void notASymbolicLink()
+        throws IOException
+    {
+        File file = new File( "src/test/resources/symlinks/src/" );
+        assertFalse(FileUtils.isSymbolicLink(file  ));
+        assertFalse(FileUtils.isSymbolicLinkLegacy(file  ));
+    }
+
+    @Test
     public void extensionUnixRootPathOnUnix()
         throws Exception
     {

Modified: maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/Java7SupportTest.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/Java7SupportTest.java?rev=1631506&r1=1631505&r2=1631506&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/Java7SupportTest.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/Java7SupportTest.java Mon Oct 13 18:42:21 2014
@@ -23,6 +23,7 @@ import java.io.File;
 
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
 public class Java7SupportTest
@@ -38,4 +39,20 @@ public class Java7SupportTest
             assertFalse( Java7Support.isSymLink( file ) );
         }
     }
+    @Test
+    public void createAndReadSymlink()
+        throws Exception
+    {
+
+        File file = new File( "target/fzz" );
+        if ( Java7Support.isJava7() )
+        {
+            Java7Support.createSymbolicLink(  file, new File("../target") );
+
+            final File file1 = Java7Support.readSymbolicLink( file );
+            assertEquals( "target", file1.getName());
+            Java7Support.delete(  file );
+        }
+    }
+
 }