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