1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
\r
3 * The contents of this file are subject to the Netscape Public
\r
4 * License Version 1.1 (the "License"); you may not use this file
\r
5 * except in compliance with the License. You may obtain a copy of
\r
6 * the License at http://www.mozilla.org/NPL/
\r
8 * Software distributed under the License is distributed on an "AS
\r
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
\r
10 * implied. See the License for the specific language governing
\r
11 * rights and limitations under the License.
\r
13 * The Original Code is Rhino code, released
\r
16 * The Initial Developer of the Original Code is Netscape
\r
17 * Communications Corporation. Portions created by Netscape are
\r
18 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
\r
26 * Alternatively, the contents of this file may be used under the
\r
27 * terms of the GNU Public License (the "GPL"), in which case the
\r
28 * provisions of the GPL are applicable instead of those above.
\r
29 * If you wish to allow use of your version of this file only
\r
30 * under the terms of the GPL and not to allow others to use your
\r
31 * version of this file under the NPL, indicate your decision by
\r
32 * deleting the provisions above and replace them with the notice
\r
33 * and other provisions required by the GPL. If you do not delete
\r
34 * the provisions above, a recipient may use your version of this
\r
35 * file under either the NPL or the GPL.
\r
38 package org.mozilla.javascript;
\r
40 import java.lang.reflect.*;
\r
43 * This class reflects Java packages into the JavaScript environment. We
\r
44 * lazily reflect classes and subpackages, and use a caching/sharing
\r
45 * system to ensure that members reflected into one JavaPackage appear
\r
46 * in all other references to the same package (as with Packages.java.lang
\r
49 * @author Mike Shaver
\r
50 * @see NativeJavaArray
\r
51 * @see NativeJavaObject
\r
52 * @see NativeJavaClass
\r
55 public class NativeJavaPackage extends ScriptableObject {
\r
57 // we know these are packages so we can skip the class check
\r
58 // note that this is ok even if the package isn't present.
\r
59 static final String[] commonPackages = {
\r
61 "java.lang.reflect",
\r
67 "java.text.resources",
\r
71 public static Scriptable init(Scriptable scope)
\r
72 throws PropertyException
\r
74 NativeJavaPackage packages = new NativeJavaPackage("");
\r
75 packages.setPrototype(getObjectPrototype(scope));
\r
76 packages.setParentScope(scope);
\r
78 // We want to get a real alias, and not a distinct JavaPackage
\r
79 // with the same packageName, so that we share classes and packages
\r
80 // that are underneath.
\r
81 NativeJavaPackage javaAlias = (NativeJavaPackage)packages.get("java",
\r
84 // It's safe to downcast here since initStandardObjects takes
\r
85 // a ScriptableObject.
\r
86 ScriptableObject global = (ScriptableObject) scope;
\r
88 global.defineProperty("Packages", packages, ScriptableObject.DONTENUM);
\r
89 global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);
\r
91 for (int i = 0; i < commonPackages.length; i++)
\r
92 packages.forcePackage(commonPackages[i]);
\r
94 if (Context.useJSObject)
\r
95 NativeJavaObject.initJSObject();
\r
97 Method[] m = FunctionObject.findMethods(NativeJavaPackage.class,
\r
98 "jsFunction_getClass");
\r
99 FunctionObject f = new FunctionObject("getClass", m[0], global);
\r
100 global.defineProperty("getClass", f, ScriptableObject.DONTENUM);
\r
102 // I think I'm supposed to return the prototype, but I don't have one.
\r
106 // set up a name which is known to be a package so we don't
\r
107 // need to look for a class by that name
\r
108 void forcePackage(String name) {
\r
109 NativeJavaPackage pkg;
\r
110 int end = name.indexOf('.');
\r
112 end = name.length();
\r
114 String id = name.substring(0, end);
\r
115 Object cached = super.get(id, this);
\r
116 if (cached != null && cached instanceof NativeJavaPackage) {
\r
117 pkg = (NativeJavaPackage) cached;
\r
119 String newPackage = packageName.length() == 0
\r
121 : packageName + "." + id;
\r
122 pkg = new NativeJavaPackage(newPackage);
\r
123 pkg.setParentScope(this);
\r
124 pkg.setPrototype(this.prototype);
\r
125 super.put(id, this, pkg);
\r
127 if (end < name.length())
\r
128 pkg.forcePackage(name.substring(end+1));
\r
131 public NativeJavaPackage(String packageName) {
\r
132 this.packageName = packageName;
\r
135 public String getClassName() {
\r
136 return "JavaPackage";
\r
139 public boolean has(String id, int index, Scriptable start) {
\r
143 public void put(String id, Scriptable start, Object value) {
\r
144 // Can't add properties to Java packages. Sorry.
\r
147 public void put(int index, Scriptable start, Object value) {
\r
148 throw Context.reportRuntimeError0("msg.pkg.int");
\r
151 public Object get(String id, Scriptable start) {
\r
152 return getPkgProperty(id, start, true);
\r
155 public Object get(int index, Scriptable start) {
\r
159 synchronized Object getPkgProperty(String name, Scriptable start,
\r
160 boolean createPkg)
\r
162 Object cached = super.get(name, start);
\r
163 if (cached != NOT_FOUND)
\r
166 String newPackage = packageName.length() == 0
\r
168 : packageName + "." + name;
\r
169 Context cx = Context.getContext();
\r
170 SecuritySupport ss = cx.getSecuritySupport();
\r
171 Scriptable newValue;
\r
174 if (ss != null && !ss.visibleToScripts(newPackage))
\r
176 throw new ClassNotFoundException();
\r
178 Class newClass = ScriptRuntime.loadClassName(newPackage);
\r
179 newValue = NativeJavaClass.wrap(getTopLevelScope(this), newClass);
\r
180 newValue.setParentScope(this);
\r
181 newValue.setPrototype(this.prototype);
\r
183 } catch (ClassNotFoundException ex) {
\r
185 NativeJavaPackage pkg = new NativeJavaPackage(newPackage);
\r
186 pkg.setParentScope(this);
\r
187 pkg.setPrototype(this.prototype);
\r
193 if (newValue != null) {
\r
194 // Make it available for fast lookup and sharing of
\r
195 // lazily-reflected constructors and static members.
\r
196 super.put(name, start, newValue);
\r
201 public Object getDefaultValue(Class ignored) {
\r
205 public String toString() {
\r
206 return "[JavaPackage " + packageName + "]";
\r
209 public static Scriptable jsFunction_getClass(Context cx,
\r
210 Scriptable thisObj,
\r
214 if (args.length > 0 && args[0] instanceof Wrapper) {
\r
215 Scriptable result = getTopLevelScope(thisObj);
\r
216 Class cl = ((Wrapper) args[0]).unwrap().getClass();
\r
217 // Evaluate the class name by getting successive properties of
\r
218 // the string to find the appropriate NativeJavaClass object
\r
219 String name = "Packages." + cl.getName();
\r
222 int index = name.indexOf('.', offset);
\r
223 String propName = index == -1
\r
224 ? name.substring(offset)
\r
225 : name.substring(offset, index);
\r
226 Object prop = result.get(propName, result);
\r
227 if (!(prop instanceof Scriptable))
\r
228 break; // fall through to error
\r
229 result = (Scriptable) prop;
\r
235 throw Context.reportRuntimeError(
\r
236 Context.getMessage0("msg.not.java.obj"));
\r
239 private String packageName;
\r