|
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 |
}
|