View Javadoc
1   package org.apache.maven.shared.utils.io;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import javax.annotation.Nonnull;
23  import java.io.File;
24  import java.io.IOException;
25  import java.lang.reflect.Array;
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  
29  /**
30   * Java7 feature detection
31   *
32   * @author Kristian Rosenvold
33   */
34  public class Java7Support
35  {
36  
37      private static final boolean IS_JAVA7;
38  
39      private static Method isSymbolicLink;
40  
41      private static Method delete;
42  
43      private static Method toPath;
44  
45      private static Method exists;
46  
47      private static Method toFile;
48  
49      private static Method readSymlink;
50  
51      private static Method createSymlink;
52  
53      private static Object emptyLinkOpts;
54  
55      private static Object emptyFileAttributes;
56  
57      static
58      {
59          boolean isJava7x = true;
60          try
61          {
62              ClassLoader cl = Thread.currentThread().getContextClassLoader();
63              Class<?> files = cl.loadClass( "java.nio.file.Files" );
64              Class<?> path = cl.loadClass( "java.nio.file.Path" );
65              Class<?> fa = cl.loadClass( "java.nio.file.attribute.FileAttribute" );
66              Class<?> linkOption = cl.loadClass( "java.nio.file.LinkOption" );
67              isSymbolicLink = files.getMethod( "isSymbolicLink", path );
68              delete = files.getMethod( "delete", path );
69              readSymlink = files.getMethod( "readSymbolicLink", path );
70  
71              emptyFileAttributes = Array.newInstance( fa, 0 );
72              final Object o = emptyFileAttributes;
73              createSymlink = files.getMethod( "createSymbolicLink", path, path, o.getClass() );
74              emptyLinkOpts = Array.newInstance( linkOption, 0 );
75              exists = files.getMethod( "exists", path, emptyLinkOpts.getClass() );
76              toPath = File.class.getMethod( "toPath" );
77              toFile = path.getMethod( "toFile" );
78          }
79          catch ( ClassNotFoundException e )
80          {
81              isJava7x = false;
82          }
83          catch ( NoSuchMethodException e )
84          {
85              isJava7x = false;
86          }
87          IS_JAVA7 = isJava7x;
88      }
89  
90      public static boolean isSymLink( @Nonnull File file )
91      {
92          try
93          {
94              Object path = toPath.invoke( file );
95              return (Boolean) isSymbolicLink.invoke( null, path );
96          }
97          catch ( IllegalAccessException e )
98          {
99              throw new RuntimeException( e );
100         }
101         catch ( InvocationTargetException e )
102         {
103             throw new RuntimeException( e );
104         }
105     }
106 
107 
108     public static @Nonnull File readSymbolicLink( @Nonnull File symlink )
109         throws IOException
110     {
111         try
112         {
113             Object path = toPath.invoke( symlink );
114             Object resultPath =  readSymlink.invoke( null, path );
115             return (File) toFile.invoke( resultPath );
116         }
117         catch ( IllegalAccessException e )
118         {
119             throw new RuntimeException( e );
120         }
121         catch ( InvocationTargetException e )
122         {
123             throw new RuntimeException( e );
124         }
125     }
126 
127 
128     public static boolean exists( @Nonnull File file )
129         throws IOException
130     {
131         try
132         {
133             Object path = toPath.invoke( file );
134             final Object invoke = exists.invoke( null, path, emptyLinkOpts );
135             return (Boolean) invoke;
136         }
137         catch ( IllegalAccessException e )
138         {
139             throw new RuntimeException( e );
140         }
141         catch ( InvocationTargetException e )
142         {
143             throw (RuntimeException) e.getTargetException();
144         }
145 
146     }
147 
148     public static @Nonnull File createSymbolicLink( @Nonnull File symlink,  @Nonnull File target )
149         throws IOException
150     {
151         try
152         {
153             if ( !exists( symlink ) )
154             {
155                 Object link = toPath.invoke( symlink );
156                 Object path = createSymlink.invoke( null, link, toPath.invoke( target ), emptyFileAttributes );
157                 return (File) toFile.invoke( path );
158             }
159             return symlink;
160         }
161         catch ( IllegalAccessException e )
162         {
163             throw new RuntimeException( e );
164         }
165         catch ( InvocationTargetException e )
166         {
167             final Throwable targetException = e.getTargetException();
168             if ( targetException instanceof IOException )
169             {
170                 throw (IOException) targetException;
171             }
172             else if ( targetException instanceof RuntimeException )
173             {
174                 // java.lang.UnsupportedOperationException: Symbolic links not supported on this operating system
175                 // java.lang.SecurityException: denies certain permissions see Javadoc
176                 throw ( RuntimeException ) targetException;
177             }
178             else
179             {
180                 throw new IOException( targetException.getClass() + ": " + targetException.getLocalizedMessage() );
181             }
182         }
183 
184     }
185     /**
186      * Performs a nio delete
187      * @param file the file to delete
188      * @throws IOException
189      */
190     public static void delete( @Nonnull File file )
191         throws IOException
192     {
193         try
194         {
195             Object path = toPath.invoke( file );
196             delete.invoke( null, path );
197         }
198         catch ( IllegalAccessException e )
199         {
200             throw new RuntimeException( e );
201         }
202         catch ( InvocationTargetException e )
203         {
204             throw (IOException) e.getTargetException();
205         }
206     }
207 
208     public static boolean isJava7()
209     {
210         return IS_JAVA7;
211     }
212 
213     public static boolean isAtLeastJava7()
214     {
215         return IS_JAVA7;
216     }
217 
218 }