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 NativeJavaPackage extends ScriptableObject {
057: static final long serialVersionUID = 7445054382212031523L;
058:
059: NativeJavaPackage(boolean internalUsage, String packageName,
060: ClassLoader classLoader) {
061: this .packageName = packageName;
062: this .classLoader = classLoader;
063: }
064:
065: /**
066: * @deprecated NativeJavaPackage is an internal class, do not use
067: * it directly.
068: */
069: public NativeJavaPackage(String packageName, ClassLoader classLoader) {
070: this (false, packageName, classLoader);
071: }
072:
073: /**
074: * @deprecated NativeJavaPackage is an internal class, do not use
075: * it directly.
076: */
077: public NativeJavaPackage(String packageName) {
078: this (false, packageName, Context.getCurrentContext()
079: .getApplicationClassLoader());
080: }
081:
082: public String getClassName() {
083: return "JavaPackage";
084: }
085:
086: public boolean has(String id, Scriptable start) {
087: return true;
088: }
089:
090: public boolean has(int index, Scriptable start) {
091: return false;
092: }
093:
094: public void put(String id, Scriptable start, Object value) {
095: // Can't add properties to Java packages. Sorry.
096: }
097:
098: public void put(int index, Scriptable start, Object value) {
099: throw Context.reportRuntimeError0("msg.pkg.int");
100: }
101:
102: public Object get(String id, Scriptable start) {
103: return getPkgProperty(id, start, true);
104: }
105:
106: public Object get(int index, Scriptable start) {
107: return NOT_FOUND;
108: }
109:
110: // set up a name which is known to be a package so we don't
111: // need to look for a class by that name
112: void forcePackage(String name, Scriptable scope) {
113: NativeJavaPackage pkg;
114: int end = name.indexOf('.');
115: if (end == -1) {
116: end = name.length();
117: }
118:
119: String id = name.substring(0, end);
120: Object cached = super .get(id, this );
121: if (cached != null && cached instanceof NativeJavaPackage) {
122: pkg = (NativeJavaPackage) cached;
123: } else {
124: String newPackage = packageName.length() == 0 ? id
125: : packageName + "." + id;
126: pkg = new NativeJavaPackage(true, newPackage, classLoader);
127: ScriptRuntime.setObjectProtoAndParent(pkg, scope);
128: super .put(id, this , pkg);
129: }
130: if (end < name.length()) {
131: pkg.forcePackage(name.substring(end + 1), scope);
132: }
133: }
134:
135: synchronized Object getPkgProperty(String name, Scriptable start,
136: boolean createPkg) {
137: Object cached = super .get(name, start);
138: if (cached != NOT_FOUND)
139: return cached;
140:
141: String className = (packageName.length() == 0) ? name
142: : packageName + '.' + name;
143: Context cx = Context.getContext();
144: ClassShutter shutter = cx.getClassShutter();
145: Scriptable newValue = null;
146: if (shutter == null || shutter.visibleToScripts(className)) {
147: Class cl = null;
148: if (classLoader != null) {
149: cl = Kit.classOrNull(classLoader, className);
150: } else {
151: cl = Kit.classOrNull(className);
152: }
153: if (cl != null) {
154: newValue = new NativeJavaClass(getTopLevelScope(this ),
155: cl);
156: newValue.setPrototype(getPrototype());
157: }
158: }
159: if (newValue == null && createPkg) {
160: NativeJavaPackage pkg;
161: pkg = new NativeJavaPackage(true, className, classLoader);
162: ScriptRuntime
163: .setObjectProtoAndParent(pkg, getParentScope());
164: newValue = pkg;
165: }
166: if (newValue != null) {
167: // Make it available for fast lookup and sharing of
168: // lazily-reflected constructors and static members.
169: super .put(name, start, newValue);
170: }
171: return newValue;
172: }
173:
174: public Object getDefaultValue(Class ignored) {
175: return toString();
176: }
177:
178: public String toString() {
179: return "[JavaPackage " + packageName + "]";
180: }
181:
182: public boolean equals(Object obj) {
183: if (obj instanceof NativeJavaPackage) {
184: NativeJavaPackage njp = (NativeJavaPackage) obj;
185: return packageName.equals(njp.packageName)
186: && classLoader == njp.classLoader;
187: }
188: return false;
189: }
190:
191: public int hashCode() {
192: return packageName.hashCode()
193: ^ (classLoader == null ? 0 : classLoader.hashCode());
194: }
195:
196: private String packageName;
197: private ClassLoader classLoader;
198: }
|