From 89bda83e0570ab87c6e449f5955613d5385e90b3 Mon Sep 17 00:00:00 2001 From: "alexanders@b2ef00c0-3703-41da-baef-cfe82387ac0c" Date: Wed, 3 Feb 2010 00:50:41 +0000 Subject: removed obsolete svn folder from hg tree --HG-- extra : convert_revision : svn%3Ab2ef00c0-3703-41da-baef-cfe82387ac0c/trunk%408 --- .../org/mozilla/javascript/NativeJavaClass.java | 320 +++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java (limited to 'infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java') diff --git a/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java new file mode 100644 index 0000000..ab8af5c --- /dev/null +++ b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java @@ -0,0 +1,320 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla 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/MPL/ + * + * 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 the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Norris Boyd + * Frank Mitchell + * Mike Shaver + * Kurt Westerfeld + * Kemal Bayram + * Ulrike Mueller + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (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 + * MPL, indicate your decision by deleting the provisions above and replacing + * 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 MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript; + +import java.lang.reflect.*; +import java.util.Hashtable; + +/** + * This class reflects Java classes into the JavaScript environment, mainly + * for constructors and static members. We lazily reflect properties, + * and currently do not guarantee that a single j.l.Class is only + * reflected once into the JS environment, although we should. + * The only known case where multiple reflections + * are possible occurs when a j.l.Class is wrapped as part of a + * method return or property access, rather than by walking the + * Packages/java tree. + * + * @author Mike Shaver + * @see NativeJavaArray + * @see NativeJavaObject + * @see NativeJavaPackage + */ + +public class NativeJavaClass extends NativeJavaObject implements Function +{ + static final long serialVersionUID = -6460763940409461664L; + + // Special property for getting the underlying Java class object. + static final String javaClassPropertyName = "__javaObject__"; + + public NativeJavaClass() { + } + + public NativeJavaClass(Scriptable scope, Class cl) { + this.parent = scope; + this.javaObject = cl; + initMembers(); + } + + protected void initMembers() { + Class cl = (Class)javaObject; + members = JavaMembers.lookupClass(parent, cl, cl, false); + staticFieldAndMethods + = members.getFieldAndMethodsObjects(this, cl, true); + } + + public String getClassName() { + return "JavaClass"; + } + + public boolean has(String name, Scriptable start) { + return members.has(name, true) || javaClassPropertyName.equals(name); + } + + public Object get(String name, Scriptable start) { + // When used as a constructor, ScriptRuntime.newObject() asks + // for our prototype to create an object of the correct type. + // We don't really care what the object is, since we're returning + // one constructed out of whole cloth, so we return null. + if (name.equals("prototype")) + return null; + + if (staticFieldAndMethods != null) { + Object result = staticFieldAndMethods.get(name); + if (result != null) + return result; + } + + if (members.has(name, true)) { + return members.get(this, name, javaObject, true); + } + + if (javaClassPropertyName.equals(name)) { + Context cx = Context.getContext(); + Scriptable scope = ScriptableObject.getTopLevelScope(start); + return cx.getWrapFactory().wrap(cx, scope, javaObject, + ScriptRuntime.ClassClass); + } + + // experimental: look for nested classes by appending $name to + // current class' name. + Class nestedClass = findNestedClass(getClassObject(), name); + if (nestedClass != null) { + NativeJavaClass nestedValue = new NativeJavaClass + (ScriptableObject.getTopLevelScope(this), nestedClass); + nestedValue.setParentScope(this); + return nestedValue; + } + + throw members.reportMemberNotFound(name); + } + + public void put(String name, Scriptable start, Object value) { + members.put(this, name, javaObject, value, true); + } + + public Object[] getIds() { + return members.getIds(true); + } + + public Class getClassObject() { + return (Class) super.unwrap(); + } + + public Object getDefaultValue(Class hint) { + if (hint == null || hint == ScriptRuntime.StringClass) + return this.toString(); + if (hint == ScriptRuntime.BooleanClass) + return Boolean.TRUE; + if (hint == ScriptRuntime.NumberClass) + return ScriptRuntime.NaNobj; + return this; + } + + public Object call(Context cx, Scriptable scope, Scriptable thisObj, + Object[] args) + { + // If it looks like a "cast" of an object to this class type, + // walk the prototype chain to see if there's a wrapper of a + // object that's an instanceof this class. + if (args.length == 1 && args[0] instanceof Scriptable) { + Class c = getClassObject(); + Scriptable p = (Scriptable) args[0]; + do { + if (p instanceof Wrapper) { + Object o = ((Wrapper) p).unwrap(); + if (c.isInstance(o)) + return p; + } + p = p.getPrototype(); + } while (p != null); + } + return construct(cx, scope, args); + } + + public Scriptable construct(Context cx, Scriptable scope, Object[] args) + { + Class classObject = getClassObject(); + int modifiers = classObject.getModifiers(); + if (! (Modifier.isInterface(modifiers) || + Modifier.isAbstract(modifiers))) + { + MemberBox[] ctors = members.ctors; + int index = NativeJavaMethod.findFunction(cx, ctors, args); + if (index < 0) { + String sig = NativeJavaMethod.scriptSignature(args); + throw Context.reportRuntimeError2( + "msg.no.java.ctor", classObject.getName(), sig); + } + + // Found the constructor, so try invoking it. + return constructSpecific(cx, scope, args, ctors[index]); + } else { + Scriptable topLevel = ScriptableObject.getTopLevelScope(this); + String msg = ""; + try { + // trying to construct an interface; use JavaAdapter to + // construct a new class on the fly that implements this + // interface. + Object v = topLevel.get("JavaAdapter", topLevel); + if (v != NOT_FOUND) { + Function f = (Function) v; + Object[] adapterArgs = { this, args[0] }; + return f.construct(cx, topLevel,adapterArgs); + } + } catch (Exception ex) { + // fall through to error + String m = ex.getMessage(); + if (m != null) + msg = m; + } + throw Context.reportRuntimeError2( + "msg.cant.instantiate", msg, classObject.getName()); + } + } + + static Scriptable constructSpecific(Context cx, Scriptable scope, + Object[] args, MemberBox ctor) + { + Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); + Class[] argTypes = ctor.argTypes; + + if (ctor.vararg) { + // marshall the explicit parameter + Object[] newArgs = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length-1; i++) { + newArgs[i] = Context.jsToJava(args[i], argTypes[i]); + } + + Object varArgs; + + // Handle special situation where a single variable parameter + // is given and it is a Java or ECMA array. + if (args.length == argTypes.length && + (args[args.length-1] == null || + args[args.length-1] instanceof NativeArray || + args[args.length-1] instanceof NativeJavaArray)) + { + // convert the ECMA array into a native array + varArgs = Context.jsToJava(args[args.length-1], + argTypes[argTypes.length - 1]); + } else { + // marshall the variable parameter + Class componentType = argTypes[argTypes.length - 1]. + getComponentType(); + varArgs = Array.newInstance(componentType, + args.length - argTypes.length + 1); + for (int i=0; i < Array.getLength(varArgs); i++) { + Object value = Context.jsToJava(args[argTypes.length-1 + i], + componentType); + Array.set(varArgs, i, value); + } + } + + // add varargs + newArgs[argTypes.length-1] = varArgs; + // replace the original args with the new one + args = newArgs; + } else { + Object[] origArgs = args; + for (int i = 0; i < args.length; i++) { + Object arg = args[i]; + Object x = Context.jsToJava(arg, argTypes[i]); + if (x != arg) { + if (args == origArgs) { + args = origArgs.clone(); + } + args[i] = x; + } + } + } + + Object instance = ctor.newInstance(args); + // we need to force this to be wrapped, because construct _has_ + // to return a scriptable + return cx.getWrapFactory().wrapNewObject(cx, topLevel, instance); + } + + public String toString() { + return "[JavaClass " + getClassObject().getName() + "]"; + } + + /** + * Determines if prototype is a wrapped Java object and performs + * a Java "instanceof". + * Exception: if value is an instance of NativeJavaClass, it isn't + * considered an instance of the Java class; this forestalls any + * name conflicts between java.lang.Class's methods and the + * static methods exposed by a JavaNativeClass. + */ + public boolean hasInstance(Scriptable value) { + + if (value instanceof Wrapper && + !(value instanceof NativeJavaClass)) { + Object instance = ((Wrapper)value).unwrap(); + + return getClassObject().isInstance(instance); + } + + // value wasn't something we understand + return false; + } + + private static Class findNestedClass(Class parentClass, String name) { + String nestedClassName = parentClass.getName() + '$' + name; + ClassLoader loader = parentClass.getClassLoader(); + if (loader == null) { + // ALERT: if loader is null, nested class should be loaded + // via system class loader which can be different from the + // loader that brought Rhino classes that Class.forName() would + // use, but ClassLoader.getSystemClassLoader() is Java 2 only + return Kit.classOrNull(nestedClassName); + } else { + return Kit.classOrNull(loader, nestedClassName); + } + } + + private Hashtable staticFieldAndMethods; +} -- cgit v1.2.3