Blame src/libbluray/bdj/java/java/io/BDFileSystem.java

Packit 5e46da
/*
Packit 5e46da
 * This file is part of libbluray
Packit 5e46da
 *
Packit 5e46da
 * This library is free software; you can redistribute it and/or
Packit 5e46da
 * modify it under the terms of the GNU Lesser General Public
Packit 5e46da
 * License as published by the Free Software Foundation; either
Packit 5e46da
 * version 2.1 of the License, or (at your option) any later version.
Packit 5e46da
 *
Packit 5e46da
 * This library is distributed in the hope that it will be useful,
Packit 5e46da
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e46da
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 5e46da
 * Lesser General Public License for more details.
Packit 5e46da
 *
Packit 5e46da
 * You should have received a copy of the GNU Lesser General Public
Packit 5e46da
 * License along with this library. If not, see
Packit 5e46da
 * <http://www.gnu.org/licenses/>.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Wrapper for java.io.FileSystem class.
Packit 5e46da
 *
Packit 5e46da
 * - replace getBooleanAttributes() for relative paths.
Packit 5e46da
 *   Pretend files exist, if those are in xlet home directory (inside .jar).
Packit 5e46da
 *   No other relative paths are allowed.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
package java.io;
Packit 5e46da
Packit 5e46da
import java.lang.reflect.Field;
Packit 5e46da
import java.lang.reflect.InvocationTargetException;
Packit 5e46da
import java.lang.reflect.Method;
Packit 5e46da
import java.lang.reflect.Modifier;
Packit 5e46da
Packit 5e46da
import java.security.AccessController;
Packit 5e46da
import java.security.PrivilegedAction;
Packit 5e46da
Packit 5e46da
import org.videolan.BDJLoader;
Packit 5e46da
import org.videolan.BDJXletContext;
Packit 5e46da
import org.videolan.Logger;
Packit 5e46da
Packit 5e46da
public abstract class BDFileSystem extends FileSystem {
Packit 5e46da
Packit 5e46da
    private static final Logger logger = Logger.getLogger(BDFileSystem.class.getName());
Packit 5e46da
Packit 5e46da
    protected final FileSystem fs;
Packit 5e46da
Packit 5e46da
    private static FileSystem nativeFileSystem;
Packit 5e46da
Packit 5e46da
    static {
Packit 5e46da
        /* Java 8: getFileSystem() no longer exists on java.io.FileSystem */
Packit 5e46da
        try {
Packit 5e46da
            nativeFileSystem = (FileSystem)Class.forName("java.io.DefaultFileSystem")
Packit 5e46da
                .getDeclaredMethod("getFileSystem", new Class[0])
Packit 5e46da
                .invoke(null, new Object[0]);
Packit 5e46da
        } catch (Exception e) {
Packit 5e46da
            try {
Packit 5e46da
                nativeFileSystem = (FileSystem)FileSystem.class
Packit 5e46da
                    .getDeclaredMethod("getFileSystem",new Class[0])
Packit 5e46da
                    .invoke(null, new Object[0]);
Packit 5e46da
            } catch (Exception t) {
Packit 5e46da
                System.err.print("Couldn't find native filesystem: " + t);
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public static void init(final Class c) {
Packit 5e46da
        AccessController.doPrivileged(
Packit 5e46da
            new PrivilegedAction() {
Packit 5e46da
                public Object run() {
Packit 5e46da
                    init0(c);
Packit 5e46da
                    return null;
Packit 5e46da
                }
Packit 5e46da
            });
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private static void init0(Class c) {
Packit 5e46da
        Field filesystem;
Packit 5e46da
        try {
Packit 5e46da
            filesystem = c.getDeclaredField("fs");
Packit 5e46da
            filesystem.setAccessible(true);
Packit 5e46da
Packit 5e46da
            /* Java 8: remove "final" modifier from the field */
Packit 5e46da
            Field modifiersField = Field.class.getDeclaredField("modifiers");
Packit 5e46da
            modifiersField.setAccessible(true);
Packit 5e46da
            modifiersField.setInt(filesystem, filesystem.getModifiers() & ~Modifier.FINAL);
Packit 5e46da
Packit 5e46da
            FileSystem fs = (FileSystem)filesystem.get(null);
Packit 5e46da
            if (fs instanceof BDFileSystemImpl) {
Packit 5e46da
                //System.err.print("FileSystem already wrapped");
Packit 5e46da
            } else {
Packit 5e46da
                filesystem.set(null, new BDFileSystemImpl(fs));
Packit 5e46da
            }
Packit 5e46da
        } catch (Exception t) {
Packit 5e46da
            System.err.print("Hooking FileSystem class failed: " + t);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public static String[] nativeList(File f) {
Packit 5e46da
        return nativeFileSystem.list(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public static boolean nativeFileExists(String path) {
Packit 5e46da
        return nativeFileSystem.getBooleanAttributes(new File(path)) != 0;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
     */
Packit 5e46da
Packit 5e46da
    public BDFileSystem(FileSystem fs) {
Packit 5e46da
        this.fs = fs;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public char getSeparator() {
Packit 5e46da
        return fs.getSeparator();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public char getPathSeparator() {
Packit 5e46da
        return fs.getPathSeparator();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String normalize(String pathname) {
Packit 5e46da
        return fs.normalize(pathname);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public int prefixLength(String pathname) {
Packit 5e46da
        return fs.prefixLength(pathname);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public static boolean isAbsolutePath(String path) {
Packit 5e46da
        return path.startsWith("/") || path.indexOf(":\\") == 1 ||
Packit 5e46da
            path.startsWith("\\");
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private String getHomeDir() {
Packit 5e46da
        String home = BDJXletContext.getCurrentXletHome();
Packit 5e46da
        if (home == null)
Packit 5e46da
            return "";
Packit 5e46da
        return home;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String resolve(String parent, String child) {
Packit 5e46da
        if (parent == null || parent.equals("") || parent.equals(".")) {
Packit 5e46da
            parent = getHomeDir();
Packit 5e46da
        }
Packit 5e46da
        else if (!isAbsolutePath(parent)) {
Packit 5e46da
            logger.info("resolve relative file at " + parent);
Packit 5e46da
            parent = getHomeDir() + parent;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        String resolvedPath = fs.resolve(parent, child);
Packit 5e46da
        String cachePath = BDJLoader.getCachedFile(resolvedPath);
Packit 5e46da
        if (cachePath != resolvedPath) {
Packit 5e46da
            logger.info("resolve(p,c): using cached " + cachePath + " (" + resolvedPath + ")");
Packit 5e46da
        }
Packit 5e46da
        return cachePath;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String getDefaultParent() {
Packit 5e46da
        return fs.getDefaultParent();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String fromURIPath(String path) {
Packit 5e46da
        return fs.fromURIPath(path);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public boolean isAbsolute(File f) {
Packit 5e46da
        return fs.isAbsolute(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String resolve(File f) {
Packit 5e46da
        if (!f.isAbsolute()) {
Packit 5e46da
            logger.info("resolve relative file " + f.getPath());
Packit 5e46da
            return resolve(BDJXletContext.getCurrentXletHome(), f.getPath());
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        String resolvedPath = fs.resolve(f);
Packit 5e46da
        String cachePath = BDJLoader.getCachedFile(resolvedPath);
Packit 5e46da
        if (cachePath != resolvedPath) {
Packit 5e46da
            logger.info("resolve(f): using cached " + cachePath + " (" + resolvedPath + ")");
Packit 5e46da
        }
Packit 5e46da
        return cachePath;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String canonicalize(String path) throws IOException {
Packit 5e46da
        String canonPath = fs.canonicalize(path);
Packit 5e46da
        String cachePath = BDJLoader.getCachedFile(canonPath);
Packit 5e46da
        if (cachePath != canonPath) {
Packit 5e46da
            logger.info("canonicalize(): Using cached " + cachePath + " for " + canonPath + "(" + path + ")");
Packit 5e46da
        }
Packit 5e46da
        return cachePath;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public int getBooleanAttributes(File f) {
Packit 5e46da
        if (f.isAbsolute()) {
Packit 5e46da
            return fs.getBooleanAttributes(f);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        /* try to locate file in Xlet home directory */
Packit 5e46da
        String home = BDJXletContext.getCurrentXletHome();
Packit 5e46da
        if (home == null) {
Packit 5e46da
            logger.error("no home found for " + f.getPath() + " at " + Logger.dumpStack());
Packit 5e46da
            return 0;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        String path = home + f.getPath();
Packit 5e46da
        logger.info("Relative path " + f.getPath() + " translated to " + path);
Packit 5e46da
        return fs.getBooleanAttributes(new File(path));
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
      ME: public abstract boolean checkAccess(File f, boolean write);
Packit 5e46da
      SE: public abstract boolean checkAccess(File f, int access);
Packit 5e46da
    */
Packit 5e46da
Packit 5e46da
    public long getLastModifiedTime(File f) {
Packit 5e46da
        return fs.getLastModifiedTime(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public long getLength(File f) {
Packit 5e46da
        if (f.isAbsolute()) {
Packit 5e46da
            return fs.getLength(f);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        /* try to locate file in Xlet home directory */
Packit 5e46da
        String home = BDJXletContext.getCurrentXletHome();
Packit 5e46da
        if (home == null) {
Packit 5e46da
            logger.error("no home found for " + f.getPath() + " at " + Logger.dumpStack());
Packit 5e46da
            return 0;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        String path = home + f.getPath();
Packit 5e46da
        logger.info("Relative path " + f.getPath() + " translated to " + path);
Packit 5e46da
        return fs.getLength(new File(path));
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
      SE only
Packit 5e46da
      public abstract boolean setPermission(File f, int access, boolean enable, boolean owneronly);
Packit 5e46da
    */
Packit 5e46da
Packit 5e46da
    /* this version exists in some java6 versions.
Packit 5e46da
     * Use reflection to make sure build succees and right method is called.
Packit 5e46da
     */
Packit 5e46da
    public boolean createFileExclusively(String path, boolean restrictive) throws IOException {
Packit 5e46da
        return createFileExclusivelyImpl(path, restrictive);
Packit 5e46da
    }
Packit 5e46da
    /* this version exists in most java versions (1.4, 1.7, some 1.6 versions) */
Packit 5e46da
    public boolean createFileExclusively(String path) throws IOException {
Packit 5e46da
        return createFileExclusivelyImpl(path, false);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private boolean createFileExclusivelyImpl(String path, boolean restrictive) throws IOException {
Packit 5e46da
        Method m;
Packit 5e46da
        Object[] args;
Packit 5e46da
Packit 5e46da
        /* resolve method and set up arguments */
Packit 5e46da
        try {
Packit 5e46da
            try {
Packit 5e46da
                m = fs.getClass().getDeclaredMethod("createFileExclusively", new Class[] { String.class });
Packit 5e46da
                args = new Object[] {(Object)path};
Packit 5e46da
            } catch (NoSuchMethodException e) {
Packit 5e46da
                m  = fs.getClass().getDeclaredMethod("createFileExclusively", new Class[] { String.class, boolean.class });
Packit 5e46da
                args = new Object[] {(Object)path, (Object)new Boolean(restrictive)};
Packit 5e46da
            }
Packit 5e46da
        } catch (NoSuchMethodException e) {
Packit 5e46da
            logger.error("no matching FileSystem.createFileExclusively found !");
Packit 5e46da
            throw new IOException();
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        /* call */
Packit 5e46da
        try {
Packit 5e46da
            Boolean result = (Boolean)m.invoke(fs, args);
Packit 5e46da
            return result.booleanValue();
Packit 5e46da
        } catch (IllegalAccessException e) {
Packit 5e46da
            logger.error("" + e);
Packit 5e46da
            throw new IOException();
Packit 5e46da
        } catch (InvocationTargetException e) {
Packit 5e46da
            Throwable t = e.getTargetException();
Packit 5e46da
            if (t instanceof IOException) {
Packit 5e46da
                throw (IOException)t;
Packit 5e46da
            }
Packit 5e46da
            logger.error("" + t);
Packit 5e46da
            throw new IOException();
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
      ME only
Packit 5e46da
      public abstract boolean deleteOnExit(File f);
Packit 5e46da
    */
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
      SE only
Packit 5e46da
      public abstract long getSpace(File f, int t);
Packit 5e46da
    */
Packit 5e46da
Packit 5e46da
    public boolean delete(File f) {
Packit 5e46da
        return fs.delete(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String[] list(File f) {
Packit 5e46da
Packit 5e46da
        String path = f.getPath();
Packit 5e46da
        String root = System.getProperty("bluray.vfs.root");
Packit 5e46da
        if (root == null || !path.startsWith(root)) {
Packit 5e46da
            /* not inside VFS */
Packit 5e46da
            return fs.list(f);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        /* path is inside VFS */
Packit 5e46da
        /* EX. HOSTEL_2 lists files in BD-ROM */
Packit 5e46da
        int rootLength = root.length();
Packit 5e46da
        path = path.substring(rootLength);
Packit 5e46da
Packit 5e46da
        String[] names = org.videolan.Libbluray.listBdFiles(path, false);
Packit 5e46da
        return names;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public boolean createDirectory(File f) {
Packit 5e46da
        return fs.createDirectory(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public boolean rename(File f1, File f2) {
Packit 5e46da
        return fs.rename(f1, f2);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public boolean setLastModifiedTime(File f, long time) {
Packit 5e46da
        return fs.setLastModifiedTime(f, time);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public boolean setReadOnly(File f) {
Packit 5e46da
        return fs.setReadOnly(f);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public File[] listRoots() {
Packit 5e46da
        return fs.listRoots();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public int compare(File f1, File f2) {
Packit 5e46da
        return fs.compare(f1, f2);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public int hashCode(File f) {
Packit 5e46da
        return fs.hashCode(f);
Packit 5e46da
    }
Packit 5e46da
}