New helper class JIFunction for easy implementation of JS functions in Java without using reflection and its usage in ImporterTopLevel and NativeJavaPackage
This commit is contained in:
igor%mir2.org 2003-05-06 18:59:22 +00:00
parent 9831ce8fc4
commit b7d1664a5d
3 changed files with 140 additions and 30 deletions

View File

@ -85,7 +85,7 @@ public class ImporterTopLevel extends ScriptableObject {
}
private void init() {
(new ImporterFunctions(this)).define(this);
ImporterFunctions.setup(this);
}
public String getClassName() {
@ -177,41 +177,44 @@ public class ImporterTopLevel extends ScriptableObject {
private ObjArray importedPackages = new ObjArray();
}
final class ImporterFunctions implements Serializable, IdFunctionMaster
final class ImporterFunctions extends JIFunction
{
ImporterFunctions(ImporterTopLevel importer)
private ImporterFunctions(ImporterTopLevel importer, int id)
{
this.importer = importer;
this.id = id;
if (id == Id_importClass) {
initNameArity("importClass", 1);
} else {
if (id != Id_importPackage) Context.codeBug();
initNameArity("importPackage", 1);
}
defineAsProperty(importer);
}
void define(Scriptable scope)
static void setup(ImporterTopLevel importer)
{
IdFunction.define(scope, "importClass", this, Id_importClass);
IdFunction.define(scope, "importPackage", this, Id_importPackage);
new ImporterFunctions(importer, Id_importClass);
new ImporterFunctions(importer, Id_importPackage);
}
public Object execMethod(int methodId, IdFunction function, Context cx,
Scriptable scope, Scriptable thisObj,
Object[] args)
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
Object[] args)
throws JavaScriptException
{
if (methodId == Id_importClass) {
if (id == Id_importClass) {
importer.importClass(cx, thisObj, args);
} else {
if (methodId != Id_importPackage) Context.codeBug();
if (id != Id_importPackage) Context.codeBug();
importer.importPackage(cx, thisObj, args);
}
return Undefined.instance;
}
public int methodArity(int methodId)
{
return 1;
}
private static final int
Id_importClass = 1,
Id_importPackage = 2;
private ImporterTopLevel importer;
private int id;
}

View File

@ -0,0 +1,105 @@
/* -*- 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):
* 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.
*/
// API class
package org.mozilla.javascript;
/**
* JIFunction or Java Implemented unction is a class to simplify implementation
* of JS functions in native code.
*/
public abstract class JIFunction extends BaseFunction
{
public JIFunction() { }
public JIFunction(String name, int arity)
{
initNameArity(name, arity);
}
protected final void initNameArity(String name, int arity)
{
this.functionName = name;
this.arity = arity;
}
public final void defineAsProperty(Scriptable scope)
{
defineAsProperty(scope, ScriptableObject.DONTENUM, false);
}
public final void defineAsProperty(Scriptable scope, int attributes)
{
defineAsProperty(scope, attributes, false);
}
public final void defineAsProperty(Scriptable scope, int attributes,
boolean sealed)
{
setParentScope(scope);
if (sealed) { sealObject(); }
ScriptableObject.defineProperty(scope, functionName, this, attributes);
}
public Scriptable getPrototype()
{
// Lazy initialization of prototype: for native functions this
// may not be called at all
Scriptable proto = super.getPrototype();
if (proto == null) {
proto = getFunctionPrototype(getParentScope());
setPrototype(proto);
}
return proto;
}
public abstract Object call(Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
throws JavaScriptException;
public int getArity()
{
return arity;
}
public int getLength()
{
return getArity();
}
private int arity;
}

View File

@ -113,7 +113,7 @@ public class NativeJavaPackage extends ScriptableObject {
public static Scriptable init(Scriptable scope)
throws PropertyException
{
NativeJavaPackage packages = new NativeJavaPackage.TopLevelPackage();
final NativeJavaPackage packages = new TopLevelPackage();
packages.setPrototype(getObjectPrototype(scope));
packages.setParentScope(scope);
@ -131,17 +131,19 @@ public class NativeJavaPackage extends ScriptableObject {
nameStart = nameEnd + 1;
}
Method[] methods = FunctionObject.getMethodList(
NativeJavaPackage.class);
Method m = FunctionObject.findSingleMethod(methods,
"jsFunction_getClass");
FunctionObject f = new FunctionObject("getClass", m, scope);
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;
global.defineProperty("getClass", f, ScriptableObject.DONTENUM);
getClass.defineAsProperty(global, ScriptableObject.DONTENUM);
global.defineProperty("Packages", packages, ScriptableObject.DONTENUM);
global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);
@ -255,17 +257,15 @@ public class NativeJavaPackage extends ScriptableObject {
return "[JavaPackage " + packageName + "]";
}
public static Scriptable jsFunction_getClass(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
static final Scriptable js_getClass(Context cx, Scriptable scope,
NativeJavaPackage top, Object[] args)
{
if (args.length > 0 && args[0] instanceof Wrapper) {
Scriptable result = getTopLevelScope(thisObj);
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 = "Packages." + cl.getName();
String name = cl.getName();
int offset = 0;
for (;;) {
int index = name.indexOf('.', offset);
@ -285,7 +285,8 @@ public class NativeJavaPackage extends ScriptableObject {
Context.getMessage0("msg.not.java.obj"));
}
private Class findClass(Context cx, String className) {
private Class findClass(Context cx, String className)
{
Class cl = null;
ClassLoader loader = classLoader;
if (loader == null) {
@ -302,3 +303,4 @@ public class NativeJavaPackage extends ScriptableObject {
private String packageName;
private ClassLoader classLoader;
}