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:
igor%mir2.org 2002-12-31 09:42:42 +00:00
Родитель 230923012a
Коммит 34427cc0a9
11 изменённых файлов: 129 добавлений и 55 удалений

Просмотреть файл

@ -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)