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 Delegator.java, released
017: * Sep 27, 2000.
018: *
019: * The Initial Developer of the Original Code is
020: * Matthias Radestock. <matthias@sorted.org>.
021: * Portions created by the Initial Developer are Copyright (C) 2000
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: *
026: * Alternatively, the contents of this file may be used under the terms of
027: * the GNU General Public License Version 2 or later (the "GPL"), in which
028: * case the provisions of the GPL are applicable instead of those above. If
029: * you wish to allow use of your version of this file only under the terms of
030: * the GPL and not to allow others to use your version of this file under the
031: * MPL, indicate your decision by deleting the provisions above and replacing
032: * them with the notice and other provisions required by the GPL. If you do
033: * not delete the provisions above, a recipient may use your version of this
034: * file under either the MPL or the GPL.
035: *
036: * ***** END LICENSE BLOCK ***** */
037:
038: // API class
039: package org.mozilla.javascript;
040:
041: /**
042: * This is a helper class for implementing wrappers around Scriptable
043: * objects. It implements the Function interface and delegates all
044: * invocations to a delegee Scriptable object. The normal use of this
045: * class involves creating a sub-class and overriding one or more of
046: * the methods.
047: *
048: * A useful application is the implementation of interceptors,
049: * pre/post conditions, debugging.
050: *
051: * @see Function
052: * @see Scriptable
053: * @author Matthias Radestock
054: */
055:
056: public class Delegator implements Function {
057:
058: protected Scriptable obj = null;
059:
060: /**
061: * Create a Delegator prototype.
062: *
063: * This constructor should only be used for creating prototype
064: * objects of Delegator.
065: *
066: * @see org.mozilla.javascript.Delegator#construct
067: */
068: public Delegator() {
069: }
070:
071: /**
072: * Create a new Delegator that forwards requests to a delegee
073: * Scriptable object.
074: *
075: * @param obj the delegee
076: * @see org.mozilla.javascript.Scriptable
077: */
078: public Delegator(Scriptable obj) {
079: this .obj = obj;
080: }
081:
082: /**
083: * Crete new Delegator instance.
084: * The default implementation calls this.getClass().newInstance().
085: *
086: * @see #construct(Context cx, Scriptable scope, Object[] args)
087: */
088: protected Delegator newInstance() {
089: try {
090: return this .getClass().newInstance();
091: } catch (Exception ex) {
092: throw Context.throwAsScriptRuntimeEx(ex);
093: }
094: }
095:
096: /**
097: * Retrieve the delegee.
098: *
099: * @return the delegee
100: */
101: public Scriptable getDelegee() {
102: return obj;
103: }
104:
105: /**
106: * Set the delegee.
107: *
108: * @param obj the delegee
109: * @see org.mozilla.javascript.Scriptable
110: */
111: public void setDelegee(Scriptable obj) {
112: this .obj = obj;
113: }
114:
115: /**
116: * @see org.mozilla.javascript.Scriptable#getClassName
117: */
118: public String getClassName() {
119: return obj.getClassName();
120: }
121:
122: /**
123: * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
124: */
125: public Object get(String name, Scriptable start) {
126: return obj.get(name, start);
127: }
128:
129: /**
130: * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
131: */
132: public Object get(int index, Scriptable start) {
133: return obj.get(index, start);
134: }
135:
136: /**
137: * @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
138: */
139: public boolean has(String name, Scriptable start) {
140: return obj.has(name, start);
141: }
142:
143: /**
144: * @see org.mozilla.javascript.Scriptable#has(int, Scriptable)
145: */
146: public boolean has(int index, Scriptable start) {
147: return obj.has(index, start);
148: }
149:
150: /**
151: * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object)
152: */
153: public void put(String name, Scriptable start, Object value) {
154: obj.put(name, start, value);
155: }
156:
157: /**
158: * @see org.mozilla.javascript.Scriptable#put(int, Scriptable, Object)
159: */
160: public void put(int index, Scriptable start, Object value) {
161: obj.put(index, start, value);
162: }
163:
164: /**
165: * @see org.mozilla.javascript.Scriptable#delete(String)
166: */
167: public void delete(String name) {
168: obj.delete(name);
169: }
170:
171: /**
172: * @see org.mozilla.javascript.Scriptable#delete(int)
173: */
174: public void delete(int index) {
175: obj.delete(index);
176: }
177:
178: /**
179: * @see org.mozilla.javascript.Scriptable#getPrototype
180: */
181: public Scriptable getPrototype() {
182: return obj.getPrototype();
183: }
184:
185: /**
186: * @see org.mozilla.javascript.Scriptable#setPrototype
187: */
188: public void setPrototype(Scriptable prototype) {
189: obj.setPrototype(prototype);
190: }
191:
192: /**
193: * @see org.mozilla.javascript.Scriptable#getParentScope
194: */
195: public Scriptable getParentScope() {
196: return obj.getParentScope();
197: }
198:
199: /**
200: * @see org.mozilla.javascript.Scriptable#setParentScope
201: */
202: public void setParentScope(Scriptable parent) {
203: obj.setParentScope(parent);
204: }
205:
206: /**
207: * @see org.mozilla.javascript.Scriptable#getIds
208: */
209: public Object[] getIds() {
210: return obj.getIds();
211: }
212:
213: /**
214: * Note that this method does not get forwarded to the delegee if
215: * the <code>hint</code> parameter is null,
216: * <code>ScriptRuntime.ScriptableClass</code> or
217: * <code>ScriptRuntime.FunctionClass</code>. Instead the object
218: * itself is returned.
219: *
220: * @param hint the type hint
221: * @return the default value
222: *
223: * @see org.mozilla.javascript.Scriptable#getDefaultValue
224: */
225: public Object getDefaultValue(Class hint) {
226: return (hint == null || hint == ScriptRuntime.ScriptableClass || hint == ScriptRuntime.FunctionClass) ? this
227: : obj.getDefaultValue(hint);
228: }
229:
230: /**
231: * @see org.mozilla.javascript.Scriptable#hasInstance
232: */
233: public boolean hasInstance(Scriptable instance) {
234: return obj.hasInstance(instance);
235: }
236:
237: /**
238: * @see org.mozilla.javascript.Function#call
239: */
240: public Object call(Context cx, Scriptable scope,
241: Scriptable this Obj, Object[] args) {
242: return ((Function) obj).call(cx, scope, this Obj, args);
243: }
244:
245: /**
246: * Note that if the <code>delegee</code> is <code>null</code>,
247: * this method creates a new instance of the Delegator itself
248: * rathert than forwarding the call to the
249: * <code>delegee</code>. This permits the use of Delegator
250: * prototypes.
251: *
252: * @param cx the current Context for this thread
253: * @param scope an enclosing scope of the caller except
254: * when the function is called from a closure.
255: * @param args the array of arguments
256: * @return the allocated object
257: *
258: * @see Function#construct(Context, Scriptable, Object[])
259: */
260: public Scriptable construct(Context cx, Scriptable scope,
261: Object[] args) {
262: if (obj == null) {
263: //this little trick allows us to declare prototype objects for
264: //Delegators
265: Delegator n = newInstance();
266: Scriptable delegee;
267: if (args.length == 0) {
268: delegee = new NativeObject();
269: } else {
270: delegee = ScriptRuntime.toObject(cx, scope, args[0]);
271: }
272: n.setDelegee(delegee);
273: return n;
274: } else {
275: return ((Function) obj).construct(cx, scope, args);
276: }
277: }
278: }
|