001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-1999
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Frank Mitchell
027: * Mike Shaver
028: *
029: * Alternatively, the contents of this file may be used under the terms of
030: * the GNU General Public License Version 2 or later (the "GPL"), in which
031: * case the provisions of the GPL are applicable instead of those above. If
032: * you wish to allow use of your version of this file only under the terms of
033: * the GPL and not to allow others to use your version of this file under the
034: * MPL, indicate your decision by deleting the provisions above and replacing
035: * them with the notice and other provisions required by the GPL. If you do
036: * not delete the provisions above, a recipient may use your version of this
037: * file under either the MPL or the GPL.
038: *
039: * ***** END LICENSE BLOCK ***** */
040:
041: package org.mozilla.javascript;
042:
043: /**
044: * This class reflects Java packages into the JavaScript environment. We
045: * lazily reflect classes and subpackages, and use a caching/sharing
046: * system to ensure that members reflected into one JavaPackage appear
047: * in all other references to the same package (as with Packages.java.lang
048: * and java.lang).
049: *
050: * @author Mike Shaver
051: * @see NativeJavaArray
052: * @see NativeJavaObject
053: * @see NativeJavaClass
054: */
055:
056: public class NativeJavaTopPackage extends NativeJavaPackage implements
057: Function, IdFunctionCall {
058: static final long serialVersionUID = -1455787259477709999L;
059:
060: // we know these are packages so we can skip the class check
061: // note that this is ok even if the package isn't present.
062: private static final String commonPackages = "" + "java.lang;"
063: + "java.lang.reflect;" + "java.io;" + "java.math;"
064: + "java.net;" + "java.util;" + "java.util.zip;"
065: + "java.text;" + "java.text.resources;" + "java.applet;"
066: + "javax.swing;";
067:
068: NativeJavaTopPackage(ClassLoader loader) {
069: super (true, "", loader);
070: }
071:
072: public Object call(Context cx, Scriptable scope,
073: Scriptable this Obj, Object[] args) {
074: return construct(cx, scope, args);
075: }
076:
077: public Scriptable construct(Context cx, Scriptable scope,
078: Object[] args) {
079: ClassLoader loader = null;
080: if (args.length != 0) {
081: Object arg = args[0];
082: if (arg instanceof Wrapper) {
083: arg = ((Wrapper) arg).unwrap();
084: }
085: if (arg instanceof ClassLoader) {
086: loader = (ClassLoader) arg;
087: }
088: }
089: if (loader == null) {
090: Context.reportRuntimeError0("msg.not.classloader");
091: return null;
092: }
093: return new NativeJavaPackage(true, "", loader);
094: }
095:
096: public static void init(Context cx, Scriptable scope, boolean sealed) {
097: ClassLoader loader = cx.getApplicationClassLoader();
098: final NativeJavaTopPackage top = new NativeJavaTopPackage(
099: loader);
100: top.setPrototype(getObjectPrototype(scope));
101: top.setParentScope(scope);
102:
103: String[] names = Kit.semicolonSplit(commonPackages);
104: for (int i = 0; i != names.length; ++i) {
105: top.forcePackage(names[i], scope);
106: }
107:
108: // getClass implementation
109: IdFunctionObject getClass = new IdFunctionObject(top, FTAG,
110: Id_getClass, "getClass", 1, scope);
111:
112: // We want to get a real alias, and not a distinct JavaPackage
113: // with the same packageName, so that we share classes and top
114: // that are underneath.
115: String[] topNames = { "java", "javax", "org", "com", "edu",
116: "net" };
117: NativeJavaPackage[] topPackages = new NativeJavaPackage[topNames.length];
118: for (int i = 0; i < topNames.length; i++) {
119: topPackages[i] = (NativeJavaPackage) top.get(topNames[i],
120: top);
121: }
122:
123: // It's safe to downcast here since initStandardObjects takes
124: // a ScriptableObject.
125: ScriptableObject global = (ScriptableObject) scope;
126:
127: if (sealed) {
128: getClass.sealObject();
129: }
130: getClass.exportAsScopeProperty();
131: global.defineProperty("Packages", top,
132: ScriptableObject.DONTENUM);
133: for (int i = 0; i < topNames.length; i++) {
134: global.defineProperty(topNames[i], topPackages[i],
135: ScriptableObject.DONTENUM);
136: }
137: }
138:
139: public Object execIdCall(IdFunctionObject f, Context cx,
140: Scriptable scope, Scriptable this Obj, Object[] args) {
141: if (f.hasTag(FTAG)) {
142: if (f.methodId() == Id_getClass) {
143: return js_getClass(cx, scope, args);
144: }
145: }
146: throw f.unknown();
147: }
148:
149: private Scriptable js_getClass(Context cx, Scriptable scope,
150: Object[] args) {
151: if (args.length > 0 && args[0] instanceof Wrapper) {
152: Scriptable result = this ;
153: Class cl = ((Wrapper) args[0]).unwrap().getClass();
154: // Evaluate the class name by getting successive properties of
155: // the string to find the appropriate NativeJavaClass object
156: String name = cl.getName();
157: int offset = 0;
158: for (;;) {
159: int index = name.indexOf('.', offset);
160: String propName = index == -1 ? name.substring(offset)
161: : name.substring(offset, index);
162: Object prop = result.get(propName, result);
163: if (!(prop instanceof Scriptable))
164: break; // fall through to error
165: result = (Scriptable) prop;
166: if (index == -1)
167: return result;
168: offset = index + 1;
169: }
170: }
171: throw Context.reportRuntimeError0("msg.not.java.obj");
172: }
173:
174: private static final Object FTAG = new Object();
175: private static final int Id_getClass = 1;
176: }
|