/*- * Copyright (C) 2014 Erik Larsson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catacombae.hfsexplorer; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date; import java.util.HashSet; import java.util.Set; /** * @author <a href="http://www.catacombae.org/" target="_top">Erik Larsson</a> */ public class Java7Util { /** * Tests whether or not the current VM is a Java 7 or higher VM. This method * should always be invoked to check that the version number of the * currently running JRE is higher than or equal to 1.7 before invoking any * of the methods in Java7Specific. * * @return whether or not the current VM is a Java 7 or higher VM. */ public static boolean isJava7OrHigher() { return System.getProperty("java.specification.version"). compareTo("1.7") >= 0; } public static void setFileTimes(String path, Date creationTime, Date lastAccessTime, Date lastModifiedTime) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class<?> pathClass = Class.forName("java.nio.file.Path"); Class<?> fileSystemsClass = Class.forName("java.nio.file.FileSystems"); Class<?> fileSystemClass = Class.forName("java.nio.file.FileSystem"); Class<?> basicFileAttributeViewClass = Class.forName("java.nio.file.attribute.BasicFileAttributeView"); Class<?> filesClass = Class.forName("java.nio.file.Files"); Class<?> linkOptionClass = Class.forName("java.nio.file.LinkOption"); Class<?> fileTimeClass = Class.forName("java.nio.file.attribute.FileTime"); /* FileSystem defaultFileSystem = FileSystems.getDefault(); */ Method fileSystemsGetDefaultMethod = fileSystemsClass.getMethod("getDefault"); Object defaultFileSystemObject = fileSystemsGetDefaultMethod.invoke(null); /* Path p = defaultFileSystem.getPath(path); */ Method fileSystemGetPathMethod = fileSystemClass.getMethod("getPath", String.class, String[].class); Object pObject = fileSystemGetPathMethod.invoke(defaultFileSystemObject, path, new String[0]); /* BasicFileAttributeView attrView = * Files.getFileAttributeView(p, BasicFileAttributeView.class, * LinkOption.NOFOLLOW_LINKS); */ Field noFollowLinksField = linkOptionClass.getField("NOFOLLOW_LINKS"); Object noFollowLinksObject = noFollowLinksField.get(null); Object linkOptionsArray = Array.newInstance(linkOptionClass, 1); Array.set(linkOptionsArray, 0, noFollowLinksObject); Method getFileAttributeViewMethod = filesClass.getMethod("getFileAttributeView", pathClass, Class.class, linkOptionsArray.getClass()); Object attrViewObject = getFileAttributeViewMethod.invoke(null, pObject, basicFileAttributeViewClass, linkOptionsArray); /* * FileTime creationFileTime; * if(creationTime != null) { * creationFileTime = FileTime.fromMillis(creationTime.getTime()); * } * else { * creationFileTime = null; * } */ Object creationFileTimeObject; if(creationTime != null) { Method fileTimefromMillisMethod = fileTimeClass.getMethod("fromMillis", long.class); creationFileTimeObject = fileTimefromMillisMethod.invoke(null, Long.valueOf(creationTime.getTime())); } else { creationFileTimeObject = null; } /* * FileTime lastAccessFileTime; * if(lastAccessTime != null) { * lastAccessFileTime = * FileTime.fromMillis(lastAccessTime.getTime()); * } * else { * lastAccessFileTime = null; * } */ Object lastAccessFileTimeObject; if(lastAccessTime != null) { Method fileTimefromMillisMethod = fileTimeClass.getMethod("fromMillis", long.class); lastAccessFileTimeObject = fileTimefromMillisMethod.invoke(null, Long.valueOf(lastAccessTime.getTime())); } else { lastAccessFileTimeObject = null; } /* * FileTime lastModifiedFileTime; * if(lastModifiedTime != null) { * lastModifiedFileTime = * FileTime.fromMillis(lastModifiedTime.getTime()); * } * else { * lastModifiedFileTime = null; * } */ Object lastModifiedFileTimeObject; if(lastModifiedTime != null) { Method fileTimefromMillisMethod = fileTimeClass.getMethod("fromMillis", long.class); lastModifiedFileTimeObject = fileTimefromMillisMethod.invoke(null, Long.valueOf(lastModifiedTime.getTime())); } else { lastModifiedFileTimeObject = null; } /* attrView.setTimes(lastModifiedFileTime, lastAccessFileTime, * creationFileTime); */ Method basicFileAttributeViewSetTimesMethod = basicFileAttributeViewClass.getMethod("setTimes", fileTimeClass, fileTimeClass, fileTimeClass); try { basicFileAttributeViewSetTimesMethod.invoke(attrViewObject, lastModifiedFileTimeObject, lastAccessFileTimeObject, creationFileTimeObject); } catch(InvocationTargetException ex) { final Throwable cause = ex.getCause(); if(cause instanceof ClassNotFoundException) { throw (ClassNotFoundException) cause; } else if(cause instanceof NoSuchMethodException) { throw (NoSuchMethodException) cause; } else if(cause instanceof IllegalAccessException) { throw (IllegalAccessException) cause; } else if(cause instanceof IllegalArgumentException) { throw (IllegalArgumentException) cause; } else if(cause instanceof InvocationTargetException) { throw (InvocationTargetException) cause; } else if(cause instanceof NoSuchFieldException) { throw (NoSuchFieldException) cause; } else if(cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { throw ex; } } } public static void setPosixPermissions(String path, boolean ownerRead, boolean ownerWrite, boolean ownerExecute, boolean groupRead, boolean groupWrite, boolean groupExecute, boolean othersRead, boolean othersWrite, boolean othersExecute) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class<?> fileSystemsClass = Class.forName("java.nio.file.FileSystems"); Class<?> fileSystemClass = Class.forName("java.nio.file.FileSystem"); Class<?> pathClass = Class.forName("java.nio.file.Path"); Class<?> posixFileAttributeViewClass = Class.forName("java.nio.file.attribute.PosixFileAttributeView"); Class<?> filesClass = Class.forName("java.nio.file.Files"); Class<?> linkOptionClass = Class.forName("java.nio.file.LinkOption"); Class<?> posixFilePermissionClass = Class.forName("java.nio.file.attribute.PosixFilePermission"); /* java.nio.file.FileSystem defaultFileSystem = java.nio.file.FileSystems.getDefault(); */ Method fileSystemsGetDefaultMethod = fileSystemsClass.getMethod("getDefault"); Object defaultFileSystemObject = fileSystemsGetDefaultMethod.invoke(null); /* java.nio.file.Path p = defaultFileSystem.getPath(path); */ Method fileSystemGetPathMethod = fileSystemClass.getMethod("getPath", String.class, String[].class); Object pObject = fileSystemGetPathMethod.invoke(defaultFileSystemObject, path, new String[0]); /* java.nio.file.attribute.PosixFileAttributeView attrView = * java.nio.file.Files.getFileAttributeView(p, * java.nio.file.attribute.PosixFileAttributeView.class, * java.nio.file.LinkOption.NOFOLLOW_LINKS); */ Field noFollowLinksField = linkOptionClass.getField("NOFOLLOW_LINKS"); Object noFollowLinksObject = noFollowLinksField.get(null); Object linkOptionsArray = Array.newInstance(linkOptionClass, 1); Array.set(linkOptionsArray, 0, noFollowLinksObject); Method getFileAttributeViewMethod = filesClass.getMethod("getFileAttributeView", pathClass, Class.class, linkOptionsArray.getClass()); Object attrViewObject = getFileAttributeViewMethod.invoke(null, pObject, posixFileAttributeViewClass, linkOptionsArray); if(attrViewObject == null) { /* No PosixFileAttributeView available. Platform does not support * POSIX attributes. Just return quietly here. */ return; } HashSet<Object> perms = new HashSet<Object>(); if(ownerRead) { Field curField = posixFilePermissionClass.getField("OWNER_READ"); Object curObject = curField.get(null); perms.add(curObject); } if(ownerWrite) { Field curField = posixFilePermissionClass.getField("OWNER_WRITE"); Object curObject = curField.get(null); perms.add(curObject); } if(ownerExecute) { Field curField = posixFilePermissionClass.getField("OWNER_EXECUTE"); Object curObject = curField.get(null); perms.add(curObject); } if(groupRead) { Field curField = posixFilePermissionClass.getField("GROUP_READ"); Object curObject = curField.get(null); perms.add(curObject); } if(groupWrite) { Field curField = posixFilePermissionClass.getField("GROUP_WRITE"); Object curObject = curField.get(null); perms.add(curObject); } if(groupExecute) { Field curField = posixFilePermissionClass.getField("GROUP_EXECUTE"); Object curObject = curField.get(null); perms.add(curObject); } if(othersRead) { Field curField = posixFilePermissionClass.getField("OTHERS_READ"); Object curObject = curField.get(null); perms.add(curObject); } if(othersWrite) { Field curField = posixFilePermissionClass.getField("OTHERS_WRITE"); Object curObject = curField.get(null); perms.add(curObject); } if(othersExecute) { Field curField = posixFilePermissionClass.getField("OTHERS_EXECUTE"); Object curObject = curField.get(null); perms.add(curObject); } /* attrView.setPermissions(perms); */ Method posixFileAttributeViewSetPermissionMethod = posixFileAttributeViewClass.getMethod("setPermissions", Set.class); try { posixFileAttributeViewSetPermissionMethod.invoke(attrViewObject, perms); } catch(InvocationTargetException ex) { final Throwable cause = ex.getCause(); if(cause instanceof ClassNotFoundException) { throw (ClassNotFoundException) cause; } else if(cause instanceof NoSuchMethodException) { throw (NoSuchMethodException) cause; } else if(cause instanceof IllegalAccessException) { throw (IllegalAccessException) cause; } else if(cause instanceof IllegalArgumentException) { throw (IllegalArgumentException) cause; } else if(cause instanceof InvocationTargetException) { throw (InvocationTargetException) cause; } else if(cause instanceof NoSuchFieldException) { throw (NoSuchFieldException) cause; } else if(cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { throw ex; } } } public static void setPosixOwners(String path, int ownerId, int groupId) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class<?> fileSystemsClass = Class.forName("java.nio.file.FileSystems"); Class<?> fileSystemClass = Class.forName("java.nio.file.FileSystem"); Class<?> pathClass = Class.forName("java.nio.file.Path"); Class<?> filesClass = Class.forName("java.nio.file.Files"); Class<?> linkOptionClass = Class.forName("java.nio.file.LinkOption"); Method fileSystemsGetDefaultMethod = fileSystemsClass.getMethod("getDefault"); Method fileSystemGetPathMethod = fileSystemClass.getMethod("getPath", String.class, String[].class); Field noFollowLinksField = linkOptionClass.getField("NOFOLLOW_LINKS"); Object noFollowLinksObject = noFollowLinksField.get(null); Object linkOptionsArray = Array.newInstance(linkOptionClass, 1); Array.set(linkOptionsArray, 0, noFollowLinksObject); /* java.nio.file.FileSystem defaultFileSystem = java.nio.file.FileSystems.getDefault(); */ Object defaultFileSystemObject = fileSystemsGetDefaultMethod.invoke(null); /* java.nio.file.Path p = defaultFileSystem.getPath(path); */ Object pObject = fileSystemGetPathMethod.invoke(defaultFileSystemObject, path, new String[0]); Method filesSetAttributeMethod = filesClass.getMethod("setAttribute", pathClass, String.class, Object.class, linkOptionsArray.getClass()); try { /* java.nio.file.Files.setAttribute(p, "unix:uid", Integer.valueOf(ownerId), java.nio.file.LinkOption.NOFOLLOW_LINKS);*/ filesSetAttributeMethod.invoke(null, pObject, "unix:uid", Integer.valueOf(ownerId), linkOptionsArray); /* java.nio.file.Files.setAttribute(p, "unix:gid", Integer.valueOf(groupId), java.nio.file.LinkOption.NOFOLLOW_LINKS); */ filesSetAttributeMethod.invoke(null, pObject, "unix:gid", Integer.valueOf(groupId), linkOptionsArray); } catch(InvocationTargetException ex) { final Throwable cause = ex.getCause(); if(cause instanceof UnsupportedOperationException) { /* Do nothing. This is expected on non-UNIX platforms. */ } else if(cause instanceof ClassNotFoundException) { throw (ClassNotFoundException) cause; } else if(cause instanceof NoSuchMethodException) { throw (NoSuchMethodException) cause; } else if(cause instanceof IllegalAccessException) { throw (IllegalAccessException) cause; } else if(cause instanceof IllegalArgumentException) { throw (IllegalArgumentException) cause; } else if(cause instanceof InvocationTargetException) { throw (InvocationTargetException) cause; } else if(cause instanceof NoSuchFieldException) { throw (NoSuchFieldException) cause; } else if(cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { throw ex; } } } public static void createSymbolicLink(String linkPathString, String targetPathString) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class<?> fileSystemsClass = Class.forName("java.nio.file.FileSystems"); Class<?> fileSystemClass = Class.forName("java.nio.file.FileSystem"); Class<?> pathClass = Class.forName("java.nio.file.Path"); Class<?> filesClass = Class.forName("java.nio.file.Files"); Class<?> fileAttributeClass = Class.forName("java.nio.file.attribute.FileAttribute"); Object emptyFileAttributeArray = Array.newInstance(fileAttributeClass, 0); Method fileSystemsGetDefaultMethod = fileSystemsClass.getMethod("getDefault"); Method fileSystemGetPathMethod = fileSystemClass.getMethod("getPath", String.class, String[].class); Method filesCreateSymbolicLinkMethod = filesClass.getMethod("createSymbolicLink", pathClass, pathClass, emptyFileAttributeArray.getClass()); /* java.nio.file.FileSystem defaultFileSystem = java.nio.file.FileSystems.getDefault(); */ Object defaultFileSystemObject = fileSystemsGetDefaultMethod.invoke(null); /* java.nio.file.Path linkPath = defaultFileSystem.getPath(linkPathString); */ Object linkPathObject = fileSystemGetPathMethod.invoke(defaultFileSystemObject, linkPathString, new String[0]); /* java.nio.file.Path targetPath = defaultFileSystem.getPath(targetPathString); */ Object targetPathObject = fileSystemGetPathMethod.invoke(defaultFileSystemObject, targetPathString, new String[0]); /* java.nio.file.Files.createSymbolicLink(linkPath, targetPath); */ try { filesCreateSymbolicLinkMethod.invoke(null, linkPathObject, targetPathObject, emptyFileAttributeArray); } catch(InvocationTargetException e) { final Throwable cause = e.getCause(); if(cause instanceof ClassNotFoundException) { throw (ClassNotFoundException) cause; } else if(cause instanceof NoSuchMethodException) { throw (NoSuchMethodException) cause; } else if(cause instanceof IllegalAccessException) { throw (IllegalAccessException) cause; } else if(cause instanceof IllegalArgumentException) { throw (IllegalArgumentException) cause; } else if(cause instanceof InvocationTargetException) { throw (InvocationTargetException) cause; } else if(cause instanceof NoSuchFieldException) { throw (NoSuchFieldException) cause; } else if(cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { throw e; } } } }