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-2000
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Igor Bukanov
027: *
028: * Alternatively, the contents of this file may be used under the terms of
029: * the GNU General Public License Version 2 or later (the "GPL"), in which
030: * case the provisions of the GPL are applicable instead of those above. If
031: * you wish to allow use of your version of this file only under the terms of
032: * the GPL and not to allow others to use your version of this file under the
033: * MPL, indicate your decision by deleting the provisions above and replacing
034: * them with the notice and other provisions required by the GPL. If you do
035: * not delete the provisions above, a recipient may use your version of this
036: * file under either the MPL or the GPL.
037: *
038: * ***** END LICENSE BLOCK ***** */
039:
040: // API class
041: package org.mozilla.javascript;
042:
043: /**
044: * Embeddings that wish to provide their own custom wrappings for Java
045: * objects may extend this class and call
046: * {@link Context#setWrapFactory(WrapFactory)}
047: * Once an instance of this class or an extension of this class is enabled
048: * for a given context (by calling setWrapFactory on that context), Rhino
049: * will call the methods of this class whenever it needs to wrap a value
050: * resulting from a call to a Java method or an access to a Java field.
051: *
052: * @see org.mozilla.javascript.Context#setWrapFactory(WrapFactory)
053: * @since 1.5 Release 4
054: */
055: public class WrapFactory {
056: /**
057: * Wrap the object.
058: * <p>
059: * The value returned must be one of
060: * <UL>
061: * <LI>java.lang.Boolean</LI>
062: * <LI>java.lang.String</LI>
063: * <LI>java.lang.Number</LI>
064: * <LI>org.mozilla.javascript.Scriptable objects</LI>
065: * <LI>The value returned by Context.getUndefinedValue()</LI>
066: * <LI>null</LI>
067: * </UL>
068: * @param cx the current Context for this thread
069: * @param scope the scope of the executing script
070: * @param obj the object to be wrapped. Note it can be null.
071: * @param staticType type hint. If security restrictions prevent to wrap
072: object based on its class, staticType will be used instead.
073: * @return the wrapped value.
074: */
075: public Object wrap(Context cx, Scriptable scope, Object obj,
076: Class staticType) {
077: if (obj == null || obj == Undefined.instance
078: || obj instanceof Scriptable) {
079: return obj;
080: }
081: if (staticType != null && staticType.isPrimitive()) {
082: if (staticType == Void.TYPE)
083: return Undefined.instance;
084: if (staticType == Character.TYPE)
085: return new Integer(((Character) obj).charValue());
086: return obj;
087: }
088: if (!isJavaPrimitiveWrap()) {
089: if (obj instanceof String || obj instanceof Number
090: || obj instanceof Boolean) {
091: return obj;
092: } else if (obj instanceof Character) {
093: return String.valueOf(((Character) obj).charValue());
094: }
095: }
096: Class cls = obj.getClass();
097: if (cls.isArray()) {
098: return NativeJavaArray.wrap(scope, obj);
099: }
100: return wrapAsJavaObject(cx, scope, obj, staticType);
101: }
102:
103: /**
104: * Wrap an object newly created by a constructor call.
105: * @param cx the current Context for this thread
106: * @param scope the scope of the executing script
107: * @param obj the object to be wrapped
108: * @return the wrapped value.
109: */
110: public Scriptable wrapNewObject(Context cx, Scriptable scope,
111: Object obj) {
112: if (obj instanceof Scriptable) {
113: return (Scriptable) obj;
114: }
115: Class cls = obj.getClass();
116: if (cls.isArray()) {
117: return NativeJavaArray.wrap(scope, obj);
118: }
119: return wrapAsJavaObject(cx, scope, obj, null);
120: }
121:
122: /**
123: * Wrap Java object as Scriptable instance to allow full access to its
124: * methods and fields from JavaScript.
125: * <p>
126: * {@link #wrap(Context, Scriptable, Object, Class)} and
127: * {@link #wrapNewObject(Context, Scriptable, Object)} call this method
128: * when they can not convert <tt>javaObject</tt> to JavaScript primitive
129: * value or JavaScript array.
130: * <p>
131: * Subclasses can override the method to provide custom wrappers
132: * for Java objects.
133: * @param cx the current Context for this thread
134: * @param scope the scope of the executing script
135: * @param javaObject the object to be wrapped
136: * @param staticType type hint. If security restrictions prevent to wrap
137: object based on its class, staticType will be used instead.
138: * @return the wrapped value which shall not be null
139: */
140: public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
141: Object javaObject, Class staticType) {
142: Scriptable wrap;
143: wrap = new NativeJavaObject(scope, javaObject, staticType);
144: return wrap;
145: }
146:
147: /**
148: * Return <code>false</code> if result of Java method, which is instance of
149: * <code>String</code>, <code>Number</code>, <code>Boolean</code> and
150: * <code>Character</code>, should be used directly as JavaScript primitive
151: * type.
152: * By default the method returns true to indicate that instances of
153: * <code>String</code>, <code>Number</code>, <code>Boolean</code> and
154: * <code>Character</code> should be wrapped as any other Java object and
155: * scripts can access any Java method available in these objects.
156: * Use {@link #setJavaPrimitiveWrap(boolean)} to change this.
157: */
158: public final boolean isJavaPrimitiveWrap() {
159: return javaPrimitiveWrap;
160: }
161:
162: /**
163: * @see #isJavaPrimitiveWrap()
164: */
165: public final void setJavaPrimitiveWrap(boolean value) {
166: Context cx = Context.getCurrentContext();
167: if (cx != null && cx.isSealed()) {
168: Context.onSealedMutation();
169: }
170: javaPrimitiveWrap = value;
171: }
172:
173: private boolean javaPrimitiveWrap = true;
174:
175: }
|