[libbluray-devel] Allow changes to boot class path at run time

npzacs git at videolan.org
Sat Sep 16 13:24:14 CEST 2017


libbluray | branch: master | npzacs <npzacs at anonymous.org> | Fri Sep 15 12:59:01 2017 +0300| [676adbd9fb43ee8002858fc578068cfb0fa6d3cc] | committer: npzacs

Allow changes to boot class path at run time

> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=676adbd9fb43ee8002858fc578068cfb0fa6d3cc
---

 .../bdj/java/org/videolan/BDJClassLoader.java      | 48 +++++++++++++++++++++-
 .../java/org/videolan/BDJClassLoaderAdapter.java   | 41 ++++++++++++++++++
 src/libbluray/bdj/java/org/videolan/Libbluray.java | 33 +++++++++++++++
 3 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/src/libbluray/bdj/java/org/videolan/BDJClassLoader.java b/src/libbluray/bdj/java/org/videolan/BDJClassLoader.java
index d2645d16..988877e4 100644
--- a/src/libbluray/bdj/java/org/videolan/BDJClassLoader.java
+++ b/src/libbluray/bdj/java/org/videolan/BDJClassLoader.java
@@ -29,6 +29,7 @@ import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.Map;
 
 import javax.tv.xlet.Xlet;
 
@@ -107,6 +108,13 @@ public class BDJClassLoader extends URLClassLoader {
     private BDJClassLoader(URL[] urls, String xletClass) {
         super(urls);
         this.xletClass = xletClass;
+
+        BDJClassLoaderAdapter a = Libbluray.getLoaderAdapter();
+        if (a != null) {
+            hideClasses = a.getHideClasses();
+            bootClasses = a.getBootClasses();
+            xletClasses = a.getXletClasses();
+        }
     }
 
     protected Xlet loadXlet() throws ClassNotFoundException,
@@ -133,7 +141,15 @@ public class BDJClassLoader extends URLClassLoader {
         this.xletClass = xletClass;
     }
 
-    public Class loadClass(String name) throws java.lang.ClassNotFoundException {
+    public Class loadClass(String name) throws ClassNotFoundException {
+
+        if (hideClasses != null) {
+            if (hideClasses.get(name) != null) {
+                logger.error("Hiding class " + name);
+                throw new ClassNotFoundException(name);
+            }
+        }
+
         /* hook FileSystem in java.io.File */
         if (name.equals("java.io.File")) {
             Class c = super.loadClass(name);
@@ -143,10 +159,21 @@ public class BDJClassLoader extends URLClassLoader {
             return c;
         }
 
+        Class bootclass = tryLoad(name, bootClasses);
+        if (bootclass != null) {
+            return bootclass;
+        }
+
         try {
             return super.loadClass(name);
         } catch (ClassNotFoundException e0) {
             logger.error("ClassNotFoundException: " + name);
+
+            Class xletclass = tryLoad(name, xletClasses);
+            if (xletclass != null) {
+                return xletclass;
+            }
+
             throw e0;
         } catch (Error err) {
             logger.error("FATAL: " + err);
@@ -154,6 +181,21 @@ public class BDJClassLoader extends URLClassLoader {
         }
     }
 
+    private Class tryLoad(String name, Map classes) {
+        if (classes != null) {
+            try {
+                byte[] code = (byte[])classes.get(name);
+                if (code != null) {
+                    logger.info("Overriding class " + name);
+                    return defineClass(code, 0, code.length);
+                }
+            } catch (Exception e) {
+                logger.error("tryLoad(" + name + ") failed: " + e);
+            }
+        }
+        return null;
+    }
+
     private byte[] loadClassCode(String name) throws ClassNotFoundException {
         String path = name.replace('.', '/').concat(".class");
 
@@ -256,5 +298,9 @@ public class BDJClassLoader extends URLClassLoader {
 
     private String xletClass;
 
+    private Map hideClasses;  /* classes that should be hidden from Xlet */
+    private Map bootClasses;  /* additional bootstrap clases */
+    private Map xletClasses;  /* fallback for possibly missing classes */
+
     private static final Logger logger = Logger.getLogger(BDJClassLoader.class.getName());
 }
diff --git a/src/libbluray/bdj/java/org/videolan/BDJClassLoaderAdapter.java b/src/libbluray/bdj/java/org/videolan/BDJClassLoaderAdapter.java
new file mode 100644
index 00000000..cac04fec
--- /dev/null
+++ b/src/libbluray/bdj/java/org/videolan/BDJClassLoaderAdapter.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of libbluray
+ * Copyright (C) 2017  VideoLAN
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+package org.videolan;
+
+import java.util.Map;
+
+public interface BDJClassLoaderAdapter {
+
+    /*
+     * Modify Xlet class path at run time
+     */
+
+     /* classes that should be hidden from Xlet.
+      * Can be used to hide profile 5 or 6 classes when
+      * running as profile 2 player.
+      */
+    public abstract Map getHideClasses();
+
+    /* Additional bootstrap classes (highest priority) */
+    public abstract Map getBootClasses();
+
+    /* normal classes (lowest priority) */
+    public abstract Map getXletClasses();
+}
diff --git a/src/libbluray/bdj/java/org/videolan/Libbluray.java b/src/libbluray/bdj/java/org/videolan/Libbluray.java
index c115deef..0f7d2aeb 100644
--- a/src/libbluray/bdj/java/org/videolan/Libbluray.java
+++ b/src/libbluray/bdj/java/org/videolan/Libbluray.java
@@ -68,6 +68,35 @@ public class Libbluray {
         System.setProperties(p);
     }
 
+    /*
+     * Loader hooks
+     */
+
+    private static BDJClassLoaderAdapter loaderAdapter = null;
+
+    protected static BDJClassLoaderAdapter getLoaderAdapter() {
+        return loaderAdapter;
+    }
+
+    private static void loadAdapter(String pkg) {
+        if (pkg == null)
+            return;
+        try {
+            final Object obj = Class.forName("org.videolan." + pkg + ".Adapter").newInstance();
+            if (obj instanceof BDJClassLoaderAdapter) {
+                loaderAdapter = (BDJClassLoaderAdapter)obj;
+            } else {
+                System.err.println("Unsupported interface in " + obj);
+            }
+        } catch (Exception e) {
+            System.err.println("" + e);
+        }
+    }
+
+    /*
+     *
+     */
+
     private static boolean initOnce = false;
     private static void initOnce() {
         if (initOnce) {
@@ -289,6 +318,9 @@ public class Libbluray {
             System.err.println("System.setSecurityManager() failed: " + ex);
             throw new SecurityException("Failed initializing SecurityManager");
         }
+
+        loadAdapter(System.getProperty("org.videolan.loader.adapter"));
+        loadAdapter(pkg);
     }
 
     /* called only from native code */
@@ -329,6 +361,7 @@ public class Libbluray {
         synchronized (bdjoFilesLock) {
             bdjoFiles = null;
         }
+        loaderAdapter = null;
     }
 
     /*



More information about the libbluray-devel mailing list