зеркало из 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;
|
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
|
public class DefiningClassLoader
|
||||||
implements GeneratedClassLoader
|
extends org.mozilla.javascript.DefiningClassLoader
|
||||||
{
|
{
|
||||||
public 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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1865,6 +1865,11 @@ public class Context {
|
||||||
*/
|
*/
|
||||||
protected void observeInstructionCount(int instructionCount) {}
|
protected void observeInstructionCount(int instructionCount) {}
|
||||||
|
|
||||||
|
public GeneratedClassLoader createClassLoader(ClassLoader parent) {
|
||||||
|
return new DefiningClassLoader(parent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/********** end of API **********/
|
/********** end of API **********/
|
||||||
|
|
||||||
static String getMessage0(String messageId) {
|
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 {
|
try {
|
||||||
Object result = method == null ? ctor.newInstance(invokeArgs)
|
Object result = method == null ? ctor.newInstance(invokeArgs)
|
||||||
: doInvoke(thisObj, invokeArgs);
|
: doInvoke(cx, thisObj, invokeArgs);
|
||||||
return hasVoidReturn ? Undefined.instance : result;
|
return hasVoidReturn ? Undefined.instance : result;
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException e) {
|
catch (InvocationTargetException e) {
|
||||||
|
@ -486,13 +486,13 @@ public class FunctionObject extends BaseFunction {
|
||||||
return super.construct(cx, scope, args);
|
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
|
throws IllegalAccessException, InvocationTargetException
|
||||||
{
|
{
|
||||||
Invoker master = invokerMaster;
|
Invoker master = invokerMaster;
|
||||||
if (master != null) {
|
if (master != null) {
|
||||||
if (invoker == null) {
|
if (invoker == null) {
|
||||||
invoker = master.createInvoker(method, types);
|
invoker = master.createInvoker(cx, method, types);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return invoker.invoke(thisObj, args);
|
return invoker.invoke(thisObj, args);
|
||||||
|
@ -510,14 +510,14 @@ public class FunctionObject extends BaseFunction {
|
||||||
try {
|
try {
|
||||||
if (parmsLength == VARARGS_METHOD) {
|
if (parmsLength == VARARGS_METHOD) {
|
||||||
Object[] invokeArgs = { cx, thisObj, args, this };
|
Object[] invokeArgs = { cx, thisObj, args, this };
|
||||||
Object result = doInvoke(null, invokeArgs);
|
Object result = doInvoke(cx, null, invokeArgs);
|
||||||
return hasVoidReturn ? Undefined.instance : result;
|
return hasVoidReturn ? Undefined.instance : result;
|
||||||
} else {
|
} else {
|
||||||
Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
|
Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
|
||||||
Object[] invokeArgs = { cx, args, this, b };
|
Object[] invokeArgs = { cx, args, this, b };
|
||||||
return (method == null)
|
return (method == null)
|
||||||
? ctor.newInstance(invokeArgs)
|
? ctor.newInstance(invokeArgs)
|
||||||
: doInvoke(null, invokeArgs);
|
: doInvoke(cx, null, invokeArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException e) {
|
catch (InvocationTargetException e) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ public abstract class Invoker {
|
||||||
public abstract Object invoke(Object that, Object [] args);
|
public abstract Object invoke(Object that, Object [] args);
|
||||||
|
|
||||||
/** Factory method to get invoker for given method */
|
/** 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -331,13 +331,14 @@ public class JavaAdapter extends ScriptableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClassLoader parentLoader = cx.getClass().getClassLoader();
|
||||||
GeneratedClassLoader loader;
|
GeneratedClassLoader loader;
|
||||||
SecurityController sc = cx.getSecurityController();
|
SecurityController sc = cx.getSecurityController();
|
||||||
if (sc == null) {
|
if (sc == null) {
|
||||||
loader = new DefiningClassLoader();
|
loader = cx.createClassLoader(parentLoader);
|
||||||
} else {
|
} else {
|
||||||
Object securityDomain = sc.getDynamicSecurityDomain(null);
|
Object securityDomain = sc.getDynamicSecurityDomain(null);
|
||||||
loader = sc.createClassLoader(securityDomain);
|
loader = sc.createClassLoader(parentLoader, securityDomain);
|
||||||
}
|
}
|
||||||
Class result = loader.defineClass(adapterName, bytes);
|
Class result = loader.defineClass(adapterName, bytes);
|
||||||
loader.linkClass(result);
|
loader.linkClass(result);
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
package org.mozilla.javascript;
|
package org.mozilla.javascript;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import org.mozilla.classfile.DefiningClassLoader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class reflects Java packages into the JavaScript environment. We
|
* 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
|
* Get class loader-like object that can be used
|
||||||
* to define classes with the given security context.
|
* 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
|
* @param securityDomain some object specifying the security
|
||||||
* context of the code that is defined by the returned class loader.
|
* context of the code that is defined by the returned class loader.
|
||||||
*/
|
*/
|
||||||
public abstract GeneratedClassLoader
|
public abstract GeneratedClassLoader
|
||||||
createClassLoader(Object securityDomain);
|
createClassLoader(ClassLoader parentLoader, Object securityDomain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get dynamic security domain that allows an action only if it is allowed
|
* 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;
|
Exception e = null;
|
||||||
Class result = null;
|
Class result = null;
|
||||||
|
ClassLoader parentLoader = cx.getClass().getClassLoader();
|
||||||
GeneratedClassLoader loader;
|
GeneratedClassLoader loader;
|
||||||
if (securityController == null) {
|
if (securityController == null) {
|
||||||
loader = new DefiningClassLoader();
|
loader = cx.createClassLoader(parentLoader);
|
||||||
} else {
|
} else {
|
||||||
loader = securityController.createClassLoader(securityDomain);
|
loader = securityController.createClassLoader(parentLoader,
|
||||||
|
securityDomain);
|
||||||
}
|
}
|
||||||
nameHelper.reset();
|
nameHelper.reset();
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,10 @@ import java.util.Hashtable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.mozilla.javascript.Invoker;
|
import org.mozilla.javascript.Invoker;
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.GeneratedClassLoader;
|
||||||
import org.mozilla.classfile.ByteCode;
|
import org.mozilla.classfile.ByteCode;
|
||||||
import org.mozilla.classfile.ClassFileWriter;
|
import org.mozilla.classfile.ClassFileWriter;
|
||||||
import org.mozilla.classfile.DefiningClassLoader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Avoid cost of java.lang.reflect.Method.invoke() by compiling a class to
|
* 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 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);
|
Invoker result;
|
||||||
if (result != null) { return result; }
|
int classNum;
|
||||||
|
|
||||||
int classNum = 0;
|
|
||||||
synchronized (this) {
|
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;
|
classNum = ++classNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +298,6 @@ public class InvokerImpl extends Invoker {
|
||||||
}
|
}
|
||||||
|
|
||||||
int classNumber;
|
int classNumber;
|
||||||
Hashtable invokersCache = new Hashtable();
|
Hashtable invokersCache;
|
||||||
DefiningClassLoader classLoader = new DefiningClassLoader();
|
GeneratedClassLoader classLoader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,9 +172,10 @@ public class JavaPolicySecurity extends SecurityProxy
|
||||||
return new ProtectionDomain(cs, pc);
|
return new ProtectionDomain(cs, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedClassLoader createClassLoader(Object securityDomain) {
|
public GeneratedClassLoader
|
||||||
|
createClassLoader(ClassLoader parentLoader, Object securityDomain) {
|
||||||
ProtectionDomain domain = (ProtectionDomain)securityDomain;
|
ProtectionDomain domain = (ProtectionDomain)securityDomain;
|
||||||
return new Loader(getClass().getClassLoader(), domain);
|
return new Loader(parentLoader, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getDynamicSecurityDomain(Object securityDomain)
|
public Object getDynamicSecurityDomain(Object securityDomain)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче