зеркало из https://github.com/mozilla/gecko-dev.git
Allow application to customize class loader used for loading generated code.
For that I added new method createClasssLoader to Context, which by default returns new instance of DefiningClassLoader and changed the code to use this method instead of creating DefiningClassLoader directly. I moved DefiningClassLoader to org.mozilla.javascript package so core Rhino classes would not depend on org.mozilla.classfile package. I also changed SecurityController.createClasssLoader to take additional parentLoader argument to explicitly specify which class loader should be parent for generated code.
This commit is contained in:
Родитель
230923012a
Коммит
34427cc0a9
|
@ -43,40 +43,13 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import org.mozilla.javascript.GeneratedClassLoader;
|
||||
|
||||
/**
|
||||
* Load generated classes.
|
||||
* @deprecated The class is moved to <tt>org.mozilla.javascript</tt>
|
||||
* package.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
* @see org.mozilla.javascript.DefiningClassLoader
|
||||
*/
|
||||
public class DefiningClassLoader extends ClassLoader
|
||||
implements GeneratedClassLoader
|
||||
public class DefiningClassLoader
|
||||
extends org.mozilla.javascript.DefiningClassLoader
|
||||
{
|
||||
public DefiningClassLoader() {
|
||||
this.parentLoader = getClass().getClassLoader();
|
||||
}
|
||||
|
||||
public Class defineClass(String name, byte[] data) {
|
||||
return super.defineClass(name, data, 0, data.length);
|
||||
}
|
||||
|
||||
public void linkClass(Class cl) {
|
||||
resolveClass(cl);
|
||||
}
|
||||
|
||||
public Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class clazz = findLoadedClass(name);
|
||||
if (clazz == null) {
|
||||
if (parentLoader != null) {
|
||||
clazz = parentLoader.loadClass(name);
|
||||
} else {
|
||||
clazz = findSystemClass(name);
|
||||
}
|
||||
}
|
||||
if (resolve)
|
||||
resolveClass(clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private ClassLoader parentLoader;
|
||||
public DefiningClassLoader() { }
|
||||
}
|
||||
|
|
|
@ -1865,6 +1865,11 @@ public class Context {
|
|||
*/
|
||||
protected void observeInstructionCount(int instructionCount) {}
|
||||
|
||||
public GeneratedClassLoader createClassLoader(ClassLoader parent) {
|
||||
return new DefiningClassLoader(parent);
|
||||
|
||||
}
|
||||
|
||||
/********** end of API **********/
|
||||
|
||||
static String getMessage0(String messageId) {
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Roger Lawrence
|
||||
* Patrick Beard
|
||||
* Igor Bukanov
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Load generated classes.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class DefiningClassLoader extends ClassLoader
|
||||
implements GeneratedClassLoader
|
||||
{
|
||||
public DefiningClassLoader() {
|
||||
this.parentLoader = getClass().getClassLoader();
|
||||
}
|
||||
|
||||
public DefiningClassLoader(ClassLoader parentLoader) {
|
||||
this.parentLoader = parentLoader;
|
||||
}
|
||||
|
||||
public Class defineClass(String name, byte[] data) {
|
||||
return super.defineClass(name, data, 0, data.length);
|
||||
}
|
||||
|
||||
public void linkClass(Class cl) {
|
||||
resolveClass(cl);
|
||||
}
|
||||
|
||||
public Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class clazz = findLoadedClass(name);
|
||||
if (clazz == null) {
|
||||
if (parentLoader != null) {
|
||||
clazz = parentLoader.loadClass(name);
|
||||
} else {
|
||||
clazz = findSystemClass(name);
|
||||
}
|
||||
}
|
||||
if (resolve)
|
||||
resolveClass(clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private ClassLoader parentLoader;
|
||||
}
|
|
@ -411,7 +411,7 @@ public class FunctionObject extends BaseFunction {
|
|||
}
|
||||
try {
|
||||
Object result = method == null ? ctor.newInstance(invokeArgs)
|
||||
: doInvoke(thisObj, invokeArgs);
|
||||
: doInvoke(cx, thisObj, invokeArgs);
|
||||
return hasVoidReturn ? Undefined.instance : result;
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
|
@ -486,13 +486,13 @@ public class FunctionObject extends BaseFunction {
|
|||
return super.construct(cx, scope, args);
|
||||
}
|
||||
|
||||
private final Object doInvoke(Object thisObj, Object[] args)
|
||||
private final Object doInvoke(Context cx, Object thisObj, Object[] args)
|
||||
throws IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
Invoker master = invokerMaster;
|
||||
if (master != null) {
|
||||
if (invoker == null) {
|
||||
invoker = master.createInvoker(method, types);
|
||||
invoker = master.createInvoker(cx, method, types);
|
||||
}
|
||||
try {
|
||||
return invoker.invoke(thisObj, args);
|
||||
|
@ -510,14 +510,14 @@ public class FunctionObject extends BaseFunction {
|
|||
try {
|
||||
if (parmsLength == VARARGS_METHOD) {
|
||||
Object[] invokeArgs = { cx, thisObj, args, this };
|
||||
Object result = doInvoke(null, invokeArgs);
|
||||
Object result = doInvoke(cx, null, invokeArgs);
|
||||
return hasVoidReturn ? Undefined.instance : result;
|
||||
} else {
|
||||
Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
|
||||
Object[] invokeArgs = { cx, args, this, b };
|
||||
return (method == null)
|
||||
? ctor.newInstance(invokeArgs)
|
||||
: doInvoke(null, invokeArgs);
|
||||
: doInvoke(cx, null, invokeArgs);
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
|
|
|
@ -47,7 +47,7 @@ public abstract class Invoker {
|
|||
public abstract Object invoke(Object that, Object [] args);
|
||||
|
||||
/** Factory method to get invoker for given method */
|
||||
public Invoker createInvoker(Method method, Class[] types) {
|
||||
public Invoker createInvoker(Context cx, Method method, Class[] types) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -331,13 +331,14 @@ public class JavaAdapter extends ScriptableObject {
|
|||
}
|
||||
}
|
||||
|
||||
ClassLoader parentLoader = cx.getClass().getClassLoader();
|
||||
GeneratedClassLoader loader;
|
||||
SecurityController sc = cx.getSecurityController();
|
||||
if (sc == null) {
|
||||
loader = new DefiningClassLoader();
|
||||
loader = cx.createClassLoader(parentLoader);
|
||||
} else {
|
||||
Object securityDomain = sc.getDynamicSecurityDomain(null);
|
||||
loader = sc.createClassLoader(securityDomain);
|
||||
loader = sc.createClassLoader(parentLoader, securityDomain);
|
||||
}
|
||||
Class result = loader.defineClass(adapterName, bytes);
|
||||
loader.linkClass(result);
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import org.mozilla.classfile.DefiningClassLoader;
|
||||
|
||||
/**
|
||||
* This class reflects Java packages into the JavaScript environment. We
|
||||
|
|
|
@ -67,11 +67,13 @@ public abstract class SecurityController {
|
|||
/**
|
||||
* Get class loader-like object that can be used
|
||||
* to define classes with the given security context.
|
||||
* @param parentLoader parent class loader to delegate search for classes
|
||||
* not defined by the class loader itself
|
||||
* @param securityDomain some object specifying the security
|
||||
* context of the code that is defined by the returned class loader.
|
||||
*/
|
||||
public abstract GeneratedClassLoader
|
||||
createClassLoader(Object securityDomain);
|
||||
createClassLoader(ClassLoader parentLoader, Object securityDomain);
|
||||
|
||||
/**
|
||||
* Get dynamic security domain that allows an action only if it is allowed
|
||||
|
|
|
@ -80,11 +80,13 @@ public class Codegen extends Interpreter {
|
|||
|
||||
Exception e = null;
|
||||
Class result = null;
|
||||
ClassLoader parentLoader = cx.getClass().getClassLoader();
|
||||
GeneratedClassLoader loader;
|
||||
if (securityController == null) {
|
||||
loader = new DefiningClassLoader();
|
||||
loader = cx.createClassLoader(parentLoader);
|
||||
} else {
|
||||
loader = securityController.createClassLoader(securityDomain);
|
||||
loader = securityController.createClassLoader(parentLoader,
|
||||
securityDomain);
|
||||
}
|
||||
nameHelper.reset();
|
||||
|
||||
|
|
|
@ -40,9 +40,10 @@ import java.util.Hashtable;
|
|||
import java.lang.reflect.Method;
|
||||
|
||||
import org.mozilla.javascript.Invoker;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.GeneratedClassLoader;
|
||||
import org.mozilla.classfile.ByteCode;
|
||||
import org.mozilla.classfile.ClassFileWriter;
|
||||
import org.mozilla.classfile.DefiningClassLoader;
|
||||
|
||||
/**
|
||||
* Avoid cost of java.lang.reflect.Method.invoke() by compiling a class to
|
||||
|
@ -50,13 +51,19 @@ import org.mozilla.classfile.DefiningClassLoader;
|
|||
*/
|
||||
public class InvokerImpl extends Invoker {
|
||||
|
||||
public Invoker createInvoker(Method method, Class[] types) {
|
||||
public Invoker createInvoker(Context cx, Method method, Class[] types) {
|
||||
|
||||
Invoker result = (Invoker)invokersCache.get(method);
|
||||
if (result != null) { return result; }
|
||||
|
||||
int classNum = 0;
|
||||
Invoker result;
|
||||
int classNum;
|
||||
synchronized (this) {
|
||||
if (invokersCache == null) {
|
||||
invokersCache = new Hashtable();
|
||||
ClassLoader parentLoader = cx.getClass().getClassLoader();
|
||||
classLoader = cx.createClassLoader(parentLoader);
|
||||
} else {
|
||||
result = (Invoker)invokersCache.get(method);
|
||||
if (result != null) { return result; }
|
||||
}
|
||||
classNum = ++classNumber;
|
||||
}
|
||||
|
||||
|
@ -291,6 +298,6 @@ public class InvokerImpl extends Invoker {
|
|||
}
|
||||
|
||||
int classNumber;
|
||||
Hashtable invokersCache = new Hashtable();
|
||||
DefiningClassLoader classLoader = new DefiningClassLoader();
|
||||
Hashtable invokersCache;
|
||||
GeneratedClassLoader classLoader;
|
||||
}
|
||||
|
|
|
@ -172,9 +172,10 @@ public class JavaPolicySecurity extends SecurityProxy
|
|||
return new ProtectionDomain(cs, pc);
|
||||
}
|
||||
|
||||
public GeneratedClassLoader createClassLoader(Object securityDomain) {
|
||||
public GeneratedClassLoader
|
||||
createClassLoader(ClassLoader parentLoader, Object securityDomain) {
|
||||
ProtectionDomain domain = (ProtectionDomain)securityDomain;
|
||||
return new Loader(getClass().getClassLoader(), domain);
|
||||
return new Loader(parentLoader, domain);
|
||||
}
|
||||
|
||||
public Object getDynamicSecurityDomain(Object securityDomain)
|
||||
|
|
Загрузка…
Ссылка в новой задаче