Code for NativeJavaPackage.TopLevelPackage is moved to a separated file NativeJavaTopPackage.java
This commit is contained in:
Родитель
31972bf975
Коммит
67749a7953
|
@ -722,15 +722,15 @@ public class Context {
|
||||||
// This creates the Packages and java package roots.
|
// This creates the Packages and java package roots.
|
||||||
new LazilyLoadedCtor(scope,
|
new LazilyLoadedCtor(scope,
|
||||||
"Packages",
|
"Packages",
|
||||||
"org.mozilla.javascript.NativeJavaPackage",
|
"org.mozilla.javascript.NativeJavaTopPackage",
|
||||||
sealed);
|
sealed);
|
||||||
new LazilyLoadedCtor(scope,
|
new LazilyLoadedCtor(scope,
|
||||||
"java",
|
"java",
|
||||||
"org.mozilla.javascript.NativeJavaPackage",
|
"org.mozilla.javascript.NativeJavaTopPackage",
|
||||||
sealed);
|
sealed);
|
||||||
new LazilyLoadedCtor(scope,
|
new LazilyLoadedCtor(scope,
|
||||||
"getClass",
|
"getClass",
|
||||||
"org.mozilla.javascript.NativeJavaPackage",
|
"org.mozilla.javascript.NativeJavaTopPackage",
|
||||||
sealed);
|
sealed);
|
||||||
|
|
||||||
// Define the JavaAdapter class, allowing it to be overridden.
|
// Define the JavaAdapter class, allowing it to be overridden.
|
||||||
|
|
|
@ -54,132 +54,6 @@ import java.lang.reflect.*;
|
||||||
|
|
||||||
public class NativeJavaPackage extends ScriptableObject {
|
public class NativeJavaPackage extends ScriptableObject {
|
||||||
|
|
||||||
// we know these are packages so we can skip the class check
|
|
||||||
// note that this is ok even if the package isn't present.
|
|
||||||
private static final String commonPackages = ""
|
|
||||||
+"java.lang;"
|
|
||||||
+"java.lang.reflect"
|
|
||||||
+"java.io;"
|
|
||||||
+"java.math;"
|
|
||||||
+"java.net;"
|
|
||||||
+"java.util;"
|
|
||||||
+"java.util.zip;"
|
|
||||||
+"java.text;"
|
|
||||||
+"java.text.resources;"
|
|
||||||
+"java.applet;"
|
|
||||||
+"javax.swing;"
|
|
||||||
;
|
|
||||||
|
|
||||||
public static class TopLevelPackage extends NativeJavaPackage
|
|
||||||
implements Function
|
|
||||||
{
|
|
||||||
public TopLevelPackage() {
|
|
||||||
super("");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
|
||||||
Object[] args)
|
|
||||||
throws JavaScriptException
|
|
||||||
{
|
|
||||||
return construct(cx, scope, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
|
||||||
throws JavaScriptException
|
|
||||||
{
|
|
||||||
ClassLoader loader = getClassLoaderFromArgs(args);
|
|
||||||
if (loader == null) {
|
|
||||||
Context.reportRuntimeError0("msg.not.classloader");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new NativeJavaPackage("", loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassLoader getClassLoaderFromArgs(Object[] args) {
|
|
||||||
if (args.length < 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Object arg = args[0];
|
|
||||||
if (arg instanceof Wrapper) {
|
|
||||||
arg = ((Wrapper)arg).unwrap();
|
|
||||||
}
|
|
||||||
if (!(arg instanceof ClassLoader)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (ClassLoader) arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public static Scriptable init(Scriptable scope)
|
|
||||||
throws PropertyException
|
|
||||||
{
|
|
||||||
final NativeJavaPackage packages = new TopLevelPackage();
|
|
||||||
packages.setPrototype(getObjectPrototype(scope));
|
|
||||||
packages.setParentScope(scope);
|
|
||||||
|
|
||||||
// We want to get a real alias, and not a distinct JavaPackage
|
|
||||||
// with the same packageName, so that we share classes and packages
|
|
||||||
// that are underneath.
|
|
||||||
NativeJavaPackage javaAlias = (NativeJavaPackage)packages.get("java",
|
|
||||||
packages);
|
|
||||||
|
|
||||||
for (int nameStart = 0; ;) {
|
|
||||||
int nameEnd = commonPackages.indexOf(';', nameStart);
|
|
||||||
if (nameEnd < 0) { break; }
|
|
||||||
String packageName = commonPackages.substring(nameStart, nameEnd);
|
|
||||||
packages.forcePackage(packageName);
|
|
||||||
nameStart = nameEnd + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
JIFunction getClass = new JIFunction("getClass", 1) {
|
|
||||||
public Object call(Context fcx, Scriptable fscope,
|
|
||||||
Scriptable thisObj, Object[] args)
|
|
||||||
{
|
|
||||||
return js_getClass(fcx, fscope, packages, args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// It's safe to downcast here since initStandardObjects takes
|
|
||||||
// a ScriptableObject.
|
|
||||||
ScriptableObject global = (ScriptableObject) scope;
|
|
||||||
|
|
||||||
getClass.defineAsProperty(global, ScriptableObject.DONTENUM);
|
|
||||||
global.defineProperty("Packages", packages, ScriptableObject.DONTENUM);
|
|
||||||
global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);
|
|
||||||
|
|
||||||
// I think I'm supposed to return the prototype, but I don't have one.
|
|
||||||
return packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up a name which is known to be a package so we don't
|
|
||||||
// need to look for a class by that name
|
|
||||||
void forcePackage(String name) {
|
|
||||||
NativeJavaPackage pkg;
|
|
||||||
int end = name.indexOf('.');
|
|
||||||
if (end == -1)
|
|
||||||
end = name.length();
|
|
||||||
|
|
||||||
String id = name.substring(0, end);
|
|
||||||
Object cached = super.get(id, this);
|
|
||||||
if (cached != null && cached instanceof NativeJavaPackage) {
|
|
||||||
pkg = (NativeJavaPackage) cached;
|
|
||||||
} else {
|
|
||||||
String newPackage = packageName.length() == 0
|
|
||||||
? id
|
|
||||||
: packageName + "." + id;
|
|
||||||
pkg = new NativeJavaPackage(newPackage, classLoader);
|
|
||||||
pkg.setParentScope(this);
|
|
||||||
pkg.setPrototype(this.prototype);
|
|
||||||
super.put(id, this, pkg);
|
|
||||||
}
|
|
||||||
if (end < name.length())
|
|
||||||
pkg.forcePackage(name.substring(end+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeJavaPackage(String packageName) {
|
|
||||||
this(packageName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeJavaPackage(String packageName, ClassLoader classLoader) {
|
public NativeJavaPackage(String packageName, ClassLoader classLoader) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
|
@ -213,6 +87,34 @@ public class NativeJavaPackage extends ScriptableObject {
|
||||||
return NOT_FOUND;
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up a name which is known to be a package so we don't
|
||||||
|
// need to look for a class by that name
|
||||||
|
void forcePackage(String name)
|
||||||
|
{
|
||||||
|
NativeJavaPackage pkg;
|
||||||
|
int end = name.indexOf('.');
|
||||||
|
if (end == -1) {
|
||||||
|
end = name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = name.substring(0, end);
|
||||||
|
Object cached = super.get(id, this);
|
||||||
|
if (cached != null && cached instanceof NativeJavaPackage) {
|
||||||
|
pkg = (NativeJavaPackage) cached;
|
||||||
|
} else {
|
||||||
|
String newPackage = packageName.length() == 0
|
||||||
|
? id
|
||||||
|
: packageName + "." + id;
|
||||||
|
pkg = new NativeJavaPackage(newPackage, classLoader);
|
||||||
|
pkg.setParentScope(this);
|
||||||
|
pkg.setPrototype(this.prototype);
|
||||||
|
super.put(id, this, pkg);
|
||||||
|
}
|
||||||
|
if (end < name.length()) {
|
||||||
|
pkg.forcePackage(name.substring(end+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
synchronized Object getPkgProperty(String name, Scriptable start,
|
synchronized Object getPkgProperty(String name, Scriptable start,
|
||||||
boolean createPkg)
|
boolean createPkg)
|
||||||
{
|
{
|
||||||
|
@ -220,14 +122,18 @@ public class NativeJavaPackage extends ScriptableObject {
|
||||||
if (cached != NOT_FOUND)
|
if (cached != NOT_FOUND)
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
String newPackage = packageName.length() == 0
|
String className = (packageName.length() == 0)
|
||||||
? name
|
? name : packageName + '.' + name;
|
||||||
: packageName + '.' + name;
|
|
||||||
Context cx = Context.getContext();
|
Context cx = Context.getContext();
|
||||||
ClassShutter shutter = cx.getClassShutter();
|
ClassShutter shutter = cx.getClassShutter();
|
||||||
Scriptable newValue = null;
|
Scriptable newValue = null;
|
||||||
if (shutter == null || shutter.visibleToScripts(newPackage)) {
|
if (shutter == null || shutter.visibleToScripts(className)) {
|
||||||
Class cl = findClass(cx, newPackage);
|
Class cl = null;
|
||||||
|
if (classLoader != null) {
|
||||||
|
cl = ScriptRuntime.classOrNull(classLoader, className);
|
||||||
|
} else {
|
||||||
|
cl = ScriptRuntime.classOrNull(className);
|
||||||
|
}
|
||||||
if (cl != null) {
|
if (cl != null) {
|
||||||
newValue = new NativeJavaClass(getTopLevelScope(this), cl);
|
newValue = new NativeJavaClass(getTopLevelScope(this), cl);
|
||||||
newValue.setParentScope(this);
|
newValue.setParentScope(this);
|
||||||
|
@ -235,7 +141,7 @@ public class NativeJavaPackage extends ScriptableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newValue == null && createPkg) {
|
if (newValue == null && createPkg) {
|
||||||
NativeJavaPackage pkg = new NativeJavaPackage(newPackage,
|
NativeJavaPackage pkg = new NativeJavaPackage(className,
|
||||||
classLoader);
|
classLoader);
|
||||||
pkg.setParentScope(this);
|
pkg.setParentScope(this);
|
||||||
pkg.setPrototype(this.prototype);
|
pkg.setPrototype(this.prototype);
|
||||||
|
@ -257,49 +163,6 @@ public class NativeJavaPackage extends ScriptableObject {
|
||||||
return "[JavaPackage " + packageName + "]";
|
return "[JavaPackage " + packageName + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
static final Scriptable js_getClass(Context cx, Scriptable scope,
|
|
||||||
NativeJavaPackage top, Object[] args)
|
|
||||||
{
|
|
||||||
if (args.length > 0 && args[0] instanceof Wrapper) {
|
|
||||||
Scriptable result = top;
|
|
||||||
Class cl = ((Wrapper) args[0]).unwrap().getClass();
|
|
||||||
// Evaluate the class name by getting successive properties of
|
|
||||||
// the string to find the appropriate NativeJavaClass object
|
|
||||||
String name = cl.getName();
|
|
||||||
int offset = 0;
|
|
||||||
for (;;) {
|
|
||||||
int index = name.indexOf('.', offset);
|
|
||||||
String propName = index == -1
|
|
||||||
? name.substring(offset)
|
|
||||||
: name.substring(offset, index);
|
|
||||||
Object prop = result.get(propName, result);
|
|
||||||
if (!(prop instanceof Scriptable))
|
|
||||||
break; // fall through to error
|
|
||||||
result = (Scriptable) prop;
|
|
||||||
if (index == -1)
|
|
||||||
return result;
|
|
||||||
offset = index+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw Context.reportRuntimeError(
|
|
||||||
Context.getMessage0("msg.not.java.obj"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class findClass(Context cx, String className)
|
|
||||||
{
|
|
||||||
Class cl = null;
|
|
||||||
ClassLoader loader = classLoader;
|
|
||||||
if (loader == null) {
|
|
||||||
loader = cx.getApplicationClassLoader();
|
|
||||||
}
|
|
||||||
if (loader != null) {
|
|
||||||
cl = ScriptRuntime.classOrNull(loader, className);
|
|
||||||
} else {
|
|
||||||
cl = ScriptRuntime.classOrNull(className);
|
|
||||||
}
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String packageName;
|
private String packageName;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* Frank Mitchell
|
||||||
|
* Mike Shaver
|
||||||
|
*
|
||||||
|
* 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.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class reflects Java packages into the JavaScript environment. We
|
||||||
|
* lazily reflect classes and subpackages, and use a caching/sharing
|
||||||
|
* system to ensure that members reflected into one JavaPackage appear
|
||||||
|
* in all other references to the same package (as with Packages.java.lang
|
||||||
|
* and java.lang).
|
||||||
|
*
|
||||||
|
* @author Mike Shaver
|
||||||
|
* @see NativeJavaArray
|
||||||
|
* @see NativeJavaObject
|
||||||
|
* @see NativeJavaClass
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NativeJavaTopPackage
|
||||||
|
extends NativeJavaPackage implements Function
|
||||||
|
{
|
||||||
|
|
||||||
|
// we know these are packages so we can skip the class check
|
||||||
|
// note that this is ok even if the package isn't present.
|
||||||
|
private static final String commonPackages = ""
|
||||||
|
+"java.lang;"
|
||||||
|
+"java.lang.reflect"
|
||||||
|
+"java.io;"
|
||||||
|
+"java.math;"
|
||||||
|
+"java.net;"
|
||||||
|
+"java.util;"
|
||||||
|
+"java.util.zip;"
|
||||||
|
+"java.text;"
|
||||||
|
+"java.text.resources;"
|
||||||
|
+"java.applet;"
|
||||||
|
+"javax.swing;"
|
||||||
|
;
|
||||||
|
|
||||||
|
public NativeJavaTopPackage(ClassLoader loader)
|
||||||
|
{
|
||||||
|
super("", loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||||
|
Object[] args)
|
||||||
|
throws JavaScriptException
|
||||||
|
{
|
||||||
|
return construct(cx, scope, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
||||||
|
throws JavaScriptException
|
||||||
|
{
|
||||||
|
ClassLoader loader = null;
|
||||||
|
if (args.length != 0) {
|
||||||
|
Object arg = args[0];
|
||||||
|
if (arg instanceof Wrapper) {
|
||||||
|
arg = ((Wrapper)arg).unwrap();
|
||||||
|
}
|
||||||
|
if (arg instanceof ClassLoader) {
|
||||||
|
loader = (ClassLoader)arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loader == null) {
|
||||||
|
Context.reportRuntimeError0("msg.not.classloader");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new NativeJavaPackage("", loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init(Context cx, Scriptable scope, boolean sealed)
|
||||||
|
throws PropertyException
|
||||||
|
{
|
||||||
|
ClassLoader loader = cx.getApplicationClassLoader();
|
||||||
|
final NativeJavaTopPackage top = new NativeJavaTopPackage(loader);
|
||||||
|
top.setPrototype(getObjectPrototype(scope));
|
||||||
|
top.setParentScope(scope);
|
||||||
|
|
||||||
|
for (int nameStart = 0; ;) {
|
||||||
|
int nameEnd = commonPackages.indexOf(';', nameStart);
|
||||||
|
if (nameEnd < 0) { break; }
|
||||||
|
String packageName = commonPackages.substring(nameStart, nameEnd);
|
||||||
|
top.forcePackage(packageName);
|
||||||
|
nameStart = nameEnd + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getClass implementation
|
||||||
|
JIFunction getClass = new JIFunction("getClass", 1) {
|
||||||
|
public Object call(Context fcx, Scriptable fscope,
|
||||||
|
Scriptable thisObj, Object[] args)
|
||||||
|
{
|
||||||
|
return top.js_getClass(fcx, fscope, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// We want to get a real alias, and not a distinct JavaPackage
|
||||||
|
// with the same packageName, so that we share classes and top
|
||||||
|
// that are underneath.
|
||||||
|
NativeJavaPackage javaAlias = (NativeJavaPackage)top.get("java",
|
||||||
|
top);
|
||||||
|
|
||||||
|
// It's safe to downcast here since initStandardObjects takes
|
||||||
|
// a ScriptableObject.
|
||||||
|
ScriptableObject global = (ScriptableObject) scope;
|
||||||
|
|
||||||
|
getClass.defineAsProperty(global, ScriptableObject.DONTENUM);
|
||||||
|
global.defineProperty("Packages", top, ScriptableObject.DONTENUM);
|
||||||
|
global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Scriptable js_getClass(Context cx, Scriptable scope, Object[] args)
|
||||||
|
{
|
||||||
|
if (args.length > 0 && args[0] instanceof Wrapper) {
|
||||||
|
Scriptable result = this;
|
||||||
|
Class cl = ((Wrapper) args[0]).unwrap().getClass();
|
||||||
|
// Evaluate the class name by getting successive properties of
|
||||||
|
// the string to find the appropriate NativeJavaClass object
|
||||||
|
String name = cl.getName();
|
||||||
|
int offset = 0;
|
||||||
|
for (;;) {
|
||||||
|
int index = name.indexOf('.', offset);
|
||||||
|
String propName = index == -1
|
||||||
|
? name.substring(offset)
|
||||||
|
: name.substring(offset, index);
|
||||||
|
Object prop = result.get(propName, result);
|
||||||
|
if (!(prop instanceof Scriptable))
|
||||||
|
break; // fall through to error
|
||||||
|
result = (Scriptable) prop;
|
||||||
|
if (index == -1)
|
||||||
|
return result;
|
||||||
|
offset = index+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Context.reportRuntimeError(
|
||||||
|
Context.getMessage0("msg.not.java.obj"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче