242 lines
7.1 KiB
Java
242 lines
7.1 KiB
Java
/*
|
|
* 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/>.
|
|
*/
|
|
|
|
/*
|
|
* BD-J support classes for libmmbd
|
|
*/
|
|
|
|
package org.videolan.mmbd;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.InputStream;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
|
|
import org.videolan.BDJClassFileTransformer;
|
|
import org.videolan.BDJClassLoaderAdapter;
|
|
import org.videolan.Logger;
|
|
|
|
import javax.media.ClockStartedError;
|
|
import javax.media.Manager;
|
|
import javax.media.NoPlayerException;
|
|
import javax.media.Player;
|
|
import javax.tv.xlet.Xlet;
|
|
import javax.tv.xlet.XletContext;
|
|
import javax.tv.xlet.XletStateChangeException;
|
|
import org.bluray.bdplus.StatusListener;
|
|
|
|
public class Adapter implements BDJClassLoaderAdapter {
|
|
|
|
public Map getHideClasses() {
|
|
return null;
|
|
}
|
|
|
|
public Map getBootClasses() {
|
|
return bootClasses;
|
|
}
|
|
|
|
public Map getXletClasses() {
|
|
return xletClasses;
|
|
}
|
|
|
|
public Adapter() throws ClassNotFoundException {
|
|
/* relocate classes to avoid runtime package collisions */
|
|
|
|
final String s1 = "org/videolan/mmbd/Adapter$Xlet";
|
|
final String s2 = "org/videolan/mmbd/Adapter$If";
|
|
Map m = new HashMap();
|
|
String d1, d2;
|
|
m.put(s1, d1 = (new String(b0) + new String(b1)));
|
|
m.put(s2, d2 = (new String(b0) + new String(b2)));
|
|
|
|
BDJClassFileTransformer t = new BDJClassFileTransformer();
|
|
byte[] c1 = t.rename(loadBootClassCode(s1), m);
|
|
byte[] c2 = t.rename(loadBootClassCode(s2), m);
|
|
|
|
if (c1 != null) {
|
|
bootClasses = new HashMap();
|
|
bootClasses.put(d1.replace('/', '.'), c1);
|
|
}
|
|
if (c2 != null) {
|
|
xletClasses = new HashMap();
|
|
xletClasses.put(d2.replace('/', '.'), c2);
|
|
}
|
|
}
|
|
|
|
public static abstract class If {
|
|
protected If() {}
|
|
}
|
|
|
|
public static class Xlet implements StatusListener {
|
|
private static Xlet instance = new Xlet();
|
|
private javax.tv.xlet.Xlet xlet = null;
|
|
private XletContext ctx = null;
|
|
|
|
static private void log(String s) {
|
|
System.out.println(s);
|
|
}
|
|
static private void error(String s) {
|
|
System.err.println(s);
|
|
}
|
|
|
|
public static Xlet initXlet(javax.tv.xlet.Xlet xlet, XletContext ctx) throws XletStateChangeException {
|
|
if ((xlet == null) || (ctx == null)) {
|
|
error("initXlet: null argument");
|
|
throw new XletStateChangeException();
|
|
}
|
|
if ((instance.xlet == xlet) && (instance.ctx == ctx)) {
|
|
error("initXlet: invalid arguments");
|
|
throw new XletStateChangeException();
|
|
}
|
|
log("initXlet");
|
|
instance.xlet = xlet;
|
|
instance.ctx = ctx;
|
|
return instance;
|
|
}
|
|
|
|
public static Xlet lookup(XletContext ctx) {
|
|
return instance;
|
|
}
|
|
|
|
public void startXlet() throws XletStateChangeException {
|
|
}
|
|
|
|
public void pauseXlet() {
|
|
}
|
|
|
|
public void destroyXlet(boolean a) {
|
|
this.instance.xlet = null;
|
|
this.instance.ctx = null;
|
|
}
|
|
|
|
public boolean isAuthRequired() {
|
|
log("isAuthRequired");
|
|
return false;
|
|
}
|
|
|
|
public void doAuth() throws InterruptedException {
|
|
doAuth(null);
|
|
}
|
|
|
|
public synchronized void doAuth(If a) throws InterruptedException, RuntimeException {
|
|
error("doAuth");
|
|
}
|
|
|
|
public void destroy() {
|
|
}
|
|
|
|
public void receive(int i) {
|
|
}
|
|
|
|
public byte[] getMMV() {
|
|
byte[] b = new byte[8];
|
|
new java.util.Random().nextBytes(b);
|
|
log("getMMV");
|
|
return b;
|
|
}
|
|
|
|
public Player createPlayer(javax.media.protocol.DataSource s) throws IOException, NoPlayerException {
|
|
return Manager.createPlayer(s);
|
|
}
|
|
|
|
public Player createPlayer(javax.media.MediaLocator l) throws IOException, NoPlayerException {
|
|
return Manager.createPlayer(l);
|
|
}
|
|
|
|
public Player createPlayer(java.net.URL u) throws IOException, NoPlayerException {
|
|
return Manager.createPlayer(u);
|
|
}
|
|
|
|
public void destroyPlayer(Player p) {
|
|
if (p == null)
|
|
return;
|
|
p.stop();
|
|
try {
|
|
p.deallocate();
|
|
} catch (ClockStartedError localClockStartedError) {
|
|
}
|
|
p.close();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* class loader
|
|
*/
|
|
|
|
private final byte[] b0 = {99,111,109,47,109,97,99,114,111,118,105,115,105,111,110,47,98,100,112,108,117,115,47};
|
|
private final byte[] b1 = {77,86,67,111,109,109};
|
|
private final byte[] b2 = {83,116,114,101,101,116,76,111,99,107,71,101,116,116,101,114};
|
|
|
|
private byte[] loadBootClassCode(String name) throws ClassNotFoundException {
|
|
final String path = name.replace('.', '/').concat(".class");
|
|
InputStream is = null;
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
byte[] buffer = new byte[0xffff];
|
|
try {
|
|
is = (InputStream)
|
|
AccessController.doPrivileged(
|
|
new PrivilegedAction() {
|
|
public Object run() {
|
|
return ClassLoader.getSystemResourceAsStream(path);
|
|
}
|
|
});
|
|
|
|
if (is == null) {
|
|
logger.error("loadBootClassCode(" + name + "): not found");
|
|
throw new ClassNotFoundException(name);
|
|
}
|
|
|
|
while (true) {
|
|
int r = is.read(buffer);
|
|
if (r == -1) {
|
|
break;
|
|
}
|
|
os.write(buffer, 0, r);
|
|
}
|
|
|
|
return os.toByteArray();
|
|
|
|
} catch (Exception e) {
|
|
logger.error("loadBootClassCode(" + name + ") failed: " + e);
|
|
throw new ClassNotFoundException(name);
|
|
|
|
} finally {
|
|
try {
|
|
if (is != null)
|
|
is.close();
|
|
} catch (IOException ioe) {
|
|
}
|
|
try {
|
|
if (os != null)
|
|
os.close();
|
|
} catch (IOException ioe) {
|
|
}
|
|
}
|
|
}
|
|
|
|
private Map bootClasses = new HashMap();
|
|
private Map xletClasses = new HashMap();
|
|
|
|
private static final Logger logger = Logger.getLogger(Adapter.class.getName());
|
|
}
|