Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[egit-dev] [JGit-io-RFC-PATCH v2 3/4] Incorporate current FileSystem Util implementations to the SPI

From: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx>

Operations such as setting executable bits if supported and resolving
relative path is incorporated with this change, as a result now it should
be possible to completely replace the currently being used util FS and
java.io.File.

Signed-off-by: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx>
---
 .../src/org/eclipse/jgit/io/Entry.java             |   35 ++++-
 .../src/org/eclipse/jgit/io/StorageSystem.java     |   16 ++
 .../eclipse/jgit/io/localfs/LocalFileEntry.java    |   52 ++++++-
 .../eclipse/jgit/io/localfs/LocalFileSystem.java   |  159 ++++++++++++++++++++
 4 files changed, 257 insertions(+), 5 deletions(-)

diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
index cd69172..5256815 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
@@ -78,6 +78,24 @@
   public boolean isExists();
 
   /**
+   * Does this operating system and JRE support the execute flag on entries?
+   *
+   * @return true if this implementation can provide reasonably accurate
+   *         executable bit information; false otherwise.
+   */
+  public boolean isExecutableSupported();
+
+  /**
+   * Determine if the entry is executable (or not).
+   * <p>
+   * Not all platforms and JREs support executable flags on entries. If the
+   * feature is unsupported this method will always return false.
+   *
+   * @return true if the entry is believed to be executable by the user.
+   */
+  public boolean isExecutable();
+
+  /**
    * Make directories upto the entry represented by this instance, provided
    * that this instance itself is a directory.
    * @return True if directories were created.
@@ -85,6 +103,19 @@
   public boolean mkdirs();
 
   /**
+   * Set an entry to be executable by the user.
+   * <p>
+   * Not all platforms and JREs support executable flags on entries. If the
+   * feature is unsupported this method will always return false and no
+   * changes will be made to the entry specified.
+   *
+   * @param executable
+   *            true to enable execution; false to disable it.
+   * @return true if the change succeeded; false otherwise.
+   */
+  public boolean setExecutable(boolean executable);
+
+  /**
    * Retrieves the URI of this entry. URI in this case acts as a primary key
    * to identify an entry.
    * @return URI to identify this entry instance
@@ -101,7 +132,7 @@
   /**
    * Retrieves the InputStream for reading the content of the entry
    * @return Input stream to read entry content
-   * @throws IOException If no such file exists or there is any other error
+   * @throws IOException If no such entry exists or there is any other error
    */
   public InputStream getInputStream()
           throws IOException;
@@ -111,7 +142,7 @@ public InputStream getInputStream()
    * opened to either overwrite it or append to it.
    * @param overwrite False if to write in append mode else true
    * @return Output stream to write content to
-   * @throws IOException If no such file exists in append mode or there is any
+   * @throws IOException If no such entry exists in append mode or there is any
    *                     error in retrieving it.
    */
   public OutputStream getOutputStream(boolean overwrite)
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
index 9f45cb3..15af614 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
@@ -65,4 +65,20 @@
    * @return Entry for current working directory.
    */
   public Entry getWorkingDirectory();
+
+  /**
+   * Retrieve the home directory of the current user
+   * @return Home directory
+   */
+  public Entry getHomeDirectory();
+
+  /**
+   * Resolve relative path with respect to a path and return the absolute
+   * entry representing the relative path.
+   * @param entry The point of reference for the relative path
+   * @param path The relative path
+   * @return The absolute entry representing the relative path entry
+   */
+  public Entry resolve(Entry entry,
+                       String path);
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
index 99df831..4ef3076 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
@@ -43,6 +43,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
@@ -60,7 +61,7 @@
         implements Entry {
 
   private File localFile;
-  private StorageSystem storageSystem;
+  private LocalFileSystem storageSystem;
 
   /**
    * Contructs an entry based of on the local file system storage and a file
@@ -70,7 +71,7 @@
    * @throws IllegalArgumentException If either argument is NULL
    */
   protected LocalFileEntry(File localFile,
-                           StorageSystem storageSystem)
+                           LocalFileSystem storageSystem)
           throws IllegalArgumentException {
     setLocalFile(localFile);
     setStorageSystem(storageSystem);
@@ -81,7 +82,7 @@ protected LocalFileEntry(File localFile,
    * @param storageSystem Storage system
    * @throws IllegalArgumentException IF storageSystem is null
    */
-  protected void setStorageSystem(StorageSystem storageSystem)
+  protected void setStorageSystem(LocalFileSystem storageSystem)
           throws IllegalArgumentException {
     if (storageSystem == null) {
       throw new IllegalArgumentException("Storage system can't be NULL!");
@@ -216,4 +217,49 @@ public StorageSystem getStorageSystem() {
   public long length() {
     return getLocalFile().length();
   }
+
+  public boolean isExecutableSupported() {
+    return LocalFileSystem.platform.isExecutableSupproted();
+  }
+
+  public boolean isExecutable() {
+    if (LocalFileSystem.platform.isExecutableSupproted()) {
+      try {
+        final Object r = LocalFileSystem.canExecute.invoke(
+                getLocalFile(),
+                (Object[]) null);
+        return ((Boolean) r).booleanValue();
+      }
+      catch (IllegalArgumentException e) {
+        throw new Error(e);
+      }
+      catch (IllegalAccessException e) {
+        throw new Error(e);
+      }
+      catch (InvocationTargetException e) {
+        throw new Error(e);
+      }
+    }
+    else {
+      return false;
+    }
+  }
+
+  public boolean setExecutable(boolean executable) {
+    try {
+      final Object r;
+      r = LocalFileSystem.setExecute.invoke(getLocalFile(), new Object[] {
+                Boolean.valueOf(executable)});
+      return ((Boolean) r).booleanValue();
+    }
+    catch (IllegalArgumentException e) {
+      throw new Error(e);
+    }
+    catch (IllegalAccessException e) {
+      throw new Error(e);
+    }
+    catch (InvocationTargetException e) {
+      throw new Error(e);
+    }
+  }
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
index d0cb536..7cef2d8 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
@@ -36,8 +36,14 @@
  */
 package org.eclipse.jgit.io.localfs;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
 import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
 
@@ -50,6 +56,14 @@
         implements StorageSystem {
 
   public static final String PROTOCOL_FILE = "file";
+  public static final Platform platform;
+  public static Method canExecute;
+  public static Method setExecute;
+  public static String cygpath;
+
+  static {
+    platform = Platform.detect();
+  }
 
   public String getURIScheme() {
     return PROTOCOL_FILE;
@@ -68,4 +82,149 @@ public Entry getWorkingDirectory() {
     String curDir = System.getProperty("user.dir");
     return new LocalFileEntry(new File(curDir), this);
   }
+
+  public Entry resolve(Entry entry,
+                       String path) {
+    if (!(entry instanceof LocalFileEntry)) {
+      return null;
+    }
+    LocalFileEntry fileEntry = (LocalFileEntry) entry;
+    File localFile = fileEntry.getLocalFile();
+    if (platform.equals(Platform.WIN32_CYGWIN)) {
+      try {
+        final Process p;
+
+        p = Runtime.getRuntime().exec(
+                new String[] {cygpath, "--windows", "--absolute", path},
+                null, localFile);
+        p.getOutputStream().close();
+
+        final BufferedReader lineRead = new BufferedReader(
+                new InputStreamReader(p.getInputStream(), "UTF-8"));
+        String r = null;
+        try {
+          r = lineRead.readLine();
+        }
+        finally {
+          lineRead.close();
+        }
+
+        for (;;) {
+          try {
+            if (p.waitFor() == 0 && r != null && r.length() > 0) {
+              return new LocalFileEntry(new File(r), this);
+            }
+            break;
+          }
+          catch (InterruptedException ie) {
+            // Stop bothering me, I have a zombie to reap.
+          }
+        }
+      }
+      catch (IOException ioe) {
+        // Fall through and use the default return.
+      }
+
+    }
+    final File abspn = new File(path);
+    if (abspn.isAbsolute()) {
+      return new LocalFileEntry(abspn, this);
+    }
+    return new LocalFileEntry(new File(localFile, path), this);
+  }
+
+  public Entry getHomeDirectory() {
+    if (platform.equals(Platform.WIN32_CYGWIN)) {
+      final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.getenv("HOME");
+        }
+      });
+      if (!(home == null || home.length() == 0)) {
+        return resolve(new LocalFileEntry(new File("."), this), home);
+      }
+    }
+    final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+      public String run() {
+        return System.getProperty("user.home");
+      }
+    });
+    if (home == null || home.length() == 0) {
+      return null;
+    }
+    return new LocalFileEntry(new File(home).getAbsoluteFile(), this);
+  }
+
+  public enum Platform {
+
+    WIN32_CYGWIN(false),
+    WIN32(false),
+    POSIX_JAVA5(false),
+    POSIX_JAVA6(true);
+    private boolean executableSupproted;
+
+    private Platform(boolean executableSupproted) {
+      this.executableSupproted = executableSupproted;
+    }
+
+    public boolean isExecutableSupproted() {
+      return executableSupproted;
+    }
+
+    public static Platform detect() {
+      final String osDotName = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.getProperty("os.name");
+        }
+      });
+      if (osDotName != null &&
+          osDotName.toLowerCase().indexOf("windows") != -1) {
+        final String path = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+          public String run() {
+            return System.getProperty("java.library.path");
+          }
+        });
+        if (path == null) {
+          return WIN32;
+        }
+        for (final String p : path.split(";")) {
+          final File e = new File(p, "cygpath.exe");
+          if (e.isFile()) {
+            cygpath = e.getAbsolutePath();
+            return WIN32_CYGWIN;
+          }
+        }
+        return WIN32;
+      }
+      else {
+        canExecute = needMethod(File.class, "canExecute");
+        setExecute = needMethod(File.class, "setExecutable",
+                Boolean.TYPE);
+        if (canExecute != null && setExecute != null) {
+          return POSIX_JAVA6;
+        }
+        else {
+          return POSIX_JAVA5;
+        }
+      }
+    }
+
+    private static Method needMethod(final Class<?> on,
+                                     final String name,
+                                     final Class<?>... args) {
+      try {
+        return on.getMethod(name, args);
+      }
+      catch (SecurityException e) {
+        return null;
+      }
+      catch (NoSuchMethodException e) {
+        return null;
+      }
+    }
+  }
 }
-- 
1.6.2.1



Back to the top