commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sebb <seb...@gmail.com>
Subject Re: svn commit: r1686472 - in /commons/proper/io/trunk/src: main/java/org/apache/commons/io/FileUtils.java main/java/org/apache/commons/io/Java7Support.java test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java
Date Fri, 19 Jun 2015 19:01:34 GMT
On 19 June 2015 at 19:00,  <krosenvold@apache.org> wrote:
> Author: krosenvold
> Date: Fri Jun 19 18:00:44 2015
> New Revision: 1686472
>
> URL: http://svn.apache.org/r1686472
> Log:
> IO-452 broken symlink support
>
> Patch by David Standish.
>
> Also added reflection-based java7 symlink support from maven code (original author is
me)
>
> Added:
>     commons/proper/io/trunk/src/main/java/org/apache/commons/io/Java7Support.java
> Modified:
>     commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java
>     commons/proper/io/trunk/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java
>
> Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java
> URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java?rev=1686472&r1=1686471&r2=1686472&view=diff
> ==============================================================================
> --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java (original)
> +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java Fri Jun
19 18:00:44 2015
> @@ -3009,8 +3009,10 @@ public class FileUtils {
>       * Will not return true if there is a Symbolic Link anywhere in the path,
>       * only if the specific file is.
>       * <p/>
> -     * <b>Note:</b> the current implementation always returns {@code false}
if the system
> -     * is detected as Windows using {@link FilenameUtils#isSystemWindows()}
> +     * When using jdk1.7, this method delegates to {@code boolean java.nio.file.Files.isSymbolicLink(Path
path)}
> +     *
> +     * <b>Note:</b> the current implementation always returns {@code false}
if running on
> +     * jkd1.6 and the system is detected as Windows using {@link FilenameUtils#isSystemWindows()}
>       * <p/>
>       * For code that runs on Java 1.7 or later, use the following method instead:
>       * <br>
> @@ -3021,6 +3023,11 @@ public class FileUtils {
>       * @since 2.0
>       */
>      public static boolean isSymlink(final File file) throws IOException {
> +        if ( Java7Support.isAtLeastJava7() )
> +        {
> +            return Java7Support.isSymLink( file );
> +        }
> +
>          if (file == null) {
>              throw new NullPointerException("File must not be null");
>          }
> @@ -3036,10 +3043,41 @@ public class FileUtils {
>          }
>
>          if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile()))
{
> -            return false;
> +            return isBrokenSymlink(file);
>          } else {
>              return true;
>          }
>      }
>
> +    /**
> +     * Determines if the specified file is possibly a broken symbolic link.
> +     *
> +     * @param file the file to check
> +
> +     * @return true if the file is a Symbolic Link
> +     * @throws IOException if an IO error occurs while checking the file
> +     */
> +    private static boolean isBrokenSymlink(final File file) throws IOException {
> +        // if file exists then if it is a symlink it's not broken
> +        if (file.exists()) {
> +            return false;
> +        }
> +        // a broken symlink will show up in the list of files of its parent directory
> +        final File canon = file.getCanonicalFile();
> +        File parentDir = canon.getParentFile();
> +        if (parentDir == null || !parentDir.exists()) {
> +            return false;
> +        }
> +
> +        // is it worthwhile to create a FileFilterUtil method for this?
> +        // is it worthwhile to create an "identity"  IOFileFilter for this?
> +        File[] fileInDir = parentDir.listFiles(
> +                new FileFilter() {
> +                    public boolean accept(File aFile) {
> +                        return aFile.equals(canon);
> +                    }
> +                }
> +        );
> +        return fileInDir.length > 0;
> +    }
>  }
>
> Added: commons/proper/io/trunk/src/main/java/org/apache/commons/io/Java7Support.java
> URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/Java7Support.java?rev=1686472&view=auto
> ==============================================================================
> --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/Java7Support.java (added)
> +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/Java7Support.java Fri
Jun 19 18:00:44 2015
> @@ -0,0 +1,199 @@
> +package org.apache.commons.io;
> +
> +/*
> + * 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.
> + */
> +
> +import java.io.File;
> +import java.io.IOException;
> +import java.lang.reflect.Array;
> +import java.lang.reflect.InvocationTargetException;
> +import java.lang.reflect.Method;
> +
> +/**
> + * Java7 feature detection and reflection based feature access.
> + *
> + * Taken from maven-shared-utils, only for private usage until we go full java7
> + */
> +class Java7Support
> +{
> +
> +    private static final boolean IS_JAVA7;
> +
> +    private static Method isSymbolicLink;
> +
> +    private static Method delete;
> +
> +    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;

The above should all be final, as for IS_JAVA7

> +
> +    static
> +    {
> +        boolean isJava7x = true;
> +        try
> +        {
> +            ClassLoader cl = Thread.currentThread().getContextClassLoader();
> +            Class<?> files = cl.loadClass( "java.nio.file.Files" );
> +            Class<?> path = cl.loadClass( "java.nio.file.Path" );
> +            Class<?> fa = cl.loadClass( "java.nio.file.attribute.FileAttribute"
);
> +            Class<?> linkOption = cl.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;

There seems to be no need to create object o.

> +            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 )
> +        {
> +            isJava7x = false;
> +        }
> +        catch ( NoSuchMethodException e )
> +        {
> +            isJava7x = false;
> +        }
> +        IS_JAVA7 = isJava7x;
> +    }
> +
> +    public static boolean isSymLink( File file )
> +    {
> +        try
> +        {
> +            Object path = toPath.invoke( file );
> +            return (Boolean) isSymbolicLink.invoke( null, path );

The Boolean should be explicitly converted to boolean.

> +        }
> +        catch ( IllegalAccessException e )
> +        {
> +            throw new RuntimeException( e );
> +        }
> +        catch ( InvocationTargetException e )
> +        {
> +            throw new RuntimeException( e );
> +        }
> +    }
> +
> +
> +    public static File readSymbolicLink( 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( File file )
> +        throws IOException
> +    {
> +        try
> +        {
> +            Object path = toPath.invoke( file );
> +            final Object invoke = exists.invoke( null, path, emptyLinkOpts );
> +            return (Boolean) invoke;

Same here, use an explicit cast.

> +        }
> +        catch ( IllegalAccessException e )
> +        {
> +            throw new RuntimeException( e );
> +        }
> +        catch ( InvocationTargetException e )
> +        {
> +            throw (RuntimeException) e.getTargetException();
> +        }
> +
> +    }
> +
> +    public static File createSymbolicLink( File symlink, 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
> +     * @throws IOException
> +     */
> +    public static void delete( File file )
> +        throws IOException
> +    {
> +        try
> +        {
> +            Object path = toPath.invoke( file );
> +            delete.invoke( null, path );
> +        }
> +        catch ( IllegalAccessException e )
> +        {
> +            throw new RuntimeException( e );
> +        }
> +        catch ( InvocationTargetException e )
> +        {
> +            throw (IOException) e.getTargetException();
> +        }
> +    }
> +
> +    public static boolean isAtLeastJava7()
> +    {
> +        return IS_JAVA7;
> +    }
> +
> +}
>
> Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java
> URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java?rev=1686472&r1=1686471&r2=1686472&view=diff
> ==============================================================================
> --- commons/proper/io/trunk/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java
(original)
> +++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java
Fri Jun 19 18:00:44 2015
> @@ -203,6 +203,25 @@ public class FileUtilsCleanSymlinksTestC
>          assertFalse(FileUtils.isSymlink(randomFile));
>      }
>
> +    public void testIdentifiesBrokenSymlinkFile() throws Exception {
> +        if (System.getProperty("os.name").startsWith("Win")) {
> +            // cant create symlinks in windows.
> +            return;
> +        }
> +
> +        final File noexistFile = new File(top, "noexist");
> +        final File symlinkFile = new File(top, "fakeinner");
> +        final File badSymlinkInPathFile = new File(symlinkFile, "fakeinner");
> +        final File noexistParentFile = new File("noexist", "file");
> +
> +        setupSymlink(noexistFile, symlinkFile);
> +
> +        assertTrue(FileUtils.isSymlink(symlinkFile));
> +        assertFalse(FileUtils.isSymlink(noexistFile));
> +        assertFalse(FileUtils.isSymlink(noexistParentFile));
> +        assertFalse(FileUtils.isSymlink(badSymlinkInPathFile));
> +    }
> +
>      public void testCorrectlyIdentifySymlinkWithParentSymLink() throws Exception {
>          if (System.getProperty("os.name").startsWith("Win")) {
>              // cant create symlinks in windows.
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message