KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > javasupport > JavaObject


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
15  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
16  * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
17  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
18  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
19  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
20  * Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
21  *
22  * Alternatively, the contents of this file may be used under the terms of
23  * either of the GNU General Public License Version 2 or later (the "GPL"),
24  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25  * in which case the provisions of the GPL or the LGPL are applicable instead
26  * of those above. If you wish to allow use of your version of this file only
27  * under the terms of either the GPL or the LGPL, and not to allow others to
28  * use your version of this file under the terms of the CPL, indicate your
29  * decision by deleting the provisions above and replace them with the notice
30  * and other provisions required by the GPL or the LGPL. If you do not delete
31  * the provisions above, a recipient may use your version of this file under
32  * the terms of any one of the CPL, the GPL or the LGPL.
33  ***** END LICENSE BLOCK *****/

34 package org.jruby.javasupport;
35
36 import org.jruby.Ruby;
37 import org.jruby.RubyClass;
38 import org.jruby.RubyFixnum;
39 import org.jruby.RubyModule;
40 import org.jruby.RubyObject;
41 import org.jruby.RubyString;
42 import org.jruby.runtime.Block;
43 import org.jruby.runtime.CallbackFactory;
44 import org.jruby.runtime.ObjectAllocator;
45 import org.jruby.runtime.builtin.IRubyObject;
46
47 /**
48  *
49  * @author jpetersen
50  */

51 public class JavaObject extends RubyObject {
52     private static Object JavaDoc NULL_LOCK = new Object JavaDoc();
53     private final Object JavaDoc value;
54
55     protected JavaObject(Ruby runtime, RubyClass rubyClass, Object JavaDoc value) {
56         super(runtime, rubyClass);
57         this.value = value;
58     }
59
60     protected JavaObject(Ruby runtime, Object JavaDoc value) {
61         this(runtime, runtime.getModule("Java").getClass("JavaObject"), value);
62     }
63
64     public static JavaObject wrap(Ruby runtime, Object JavaDoc value) {
65         Object JavaDoc lock = value == null ? NULL_LOCK : value;
66         
67         synchronized (lock) {
68             JavaObject wrapper = runtime.getJavaSupport().getJavaObjectFromCache(value);
69             if (wrapper == null) {
70                 if (value == null) {
71                     wrapper = new JavaObject(runtime, value);
72                 } else if (value.getClass().isArray()) {
73                     wrapper = new JavaArray(runtime, value);
74                 } else if (value.getClass().equals(Class JavaDoc.class)) {
75                     wrapper = JavaClass.get(runtime, (Class JavaDoc)value);
76                 } else {
77                     wrapper = new JavaObject(runtime, value);
78                 }
79                 runtime.getJavaSupport().putJavaObjectIntoCache(wrapper);
80             }
81             return wrapper;
82         }
83     }
84
85     public Class JavaDoc getJavaClass() {
86         return value != null ? value.getClass() : Void.TYPE;
87     }
88
89     public Object JavaDoc getValue() {
90         return value;
91     }
92
93     public static RubyClass createJavaObjectClass(Ruby runtime, RubyModule javaModule) {
94         // FIXME: Ideally JavaObject instances should be marshallable, which means that
95
// the JavaObject metaclass should have an appropriate allocator. JRUBY-414
96
RubyClass result = javaModule.defineClassUnder("JavaObject", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
97
98         registerRubyMethods(runtime, result);
99
100         result.getMetaClass().undefineMethod("new");
101         result.getMetaClass().undefineMethod("allocate");
102
103         return result;
104     }
105
106     protected static void registerRubyMethods(Ruby runtime, RubyClass result) {
107         CallbackFactory callbackFactory = runtime.callbackFactory(JavaObject.class);
108
109         result.defineFastMethod("to_s", callbackFactory.getFastMethod("to_s"));
110         result.defineFastMethod("==", callbackFactory.getFastMethod("equal", IRubyObject.class));
111         result.defineFastMethod("eql?", callbackFactory.getFastMethod("equal", IRubyObject.class));
112         result.defineFastMethod("equal?", callbackFactory.getFastMethod("same", IRubyObject.class));
113         result.defineFastMethod("hash", callbackFactory.getFastMethod("hash"));
114         result.defineFastMethod("java_type", callbackFactory.getFastMethod("java_type"));
115         result.defineFastMethod("java_class", callbackFactory.getFastMethod("java_class"));
116         result.defineFastMethod("java_proxy?", callbackFactory.getFastMethod("is_java_proxy"));
117         result.defineMethod("synchronized", callbackFactory.getMethod("ruby_synchronized"));
118         result.defineFastMethod("length", callbackFactory.getFastMethod("length"));
119         result.defineFastMethod("[]", callbackFactory.getFastMethod("aref", IRubyObject.class));
120         result.defineFastMethod("[]=", callbackFactory.getFastMethod("aset", IRubyObject.class, IRubyObject.class));
121         result.defineFastMethod("fill", callbackFactory.getFastMethod("afill", IRubyObject.class, IRubyObject.class, IRubyObject.class));
122     }
123
124     public RubyFixnum hash() {
125         return getRuntime().newFixnum(value == null ? 0 : value.hashCode());
126     }
127
128     public IRubyObject to_s() {
129         return getRuntime().newString(
130            value == null ? "null" : value.toString());
131     }
132
133     public IRubyObject equal(IRubyObject other) {
134         if (!(other instanceof JavaObject)) {
135             other = other.getInstanceVariable("@java_object");
136             if (!(other instanceof JavaObject)) {
137                 return getRuntime().getFalse();
138             }
139         }
140         
141         if (getValue() == null && ((JavaObject) other).getValue() == null) {
142             return getRuntime().getTrue();
143         }
144         
145         boolean isEqual = getValue().equals(((JavaObject) other).getValue());
146         return isEqual ? getRuntime().getTrue() : getRuntime().getFalse();
147     }
148     
149     public IRubyObject same(IRubyObject other) {
150         if (!(other instanceof JavaObject)) {
151             other = other.getInstanceVariable("@java_object");
152             if (!(other instanceof JavaObject)) {
153               return getRuntime().getFalse();
154             }
155         }
156       
157         if (getValue() == null && ((JavaObject) other).getValue() == null) {
158             return getRuntime().getTrue();
159         }
160       
161         boolean isSame = getValue() == ((JavaObject) other).getValue();
162         return isSame ? getRuntime().getTrue() : getRuntime().getFalse();
163     }
164
165     public RubyString java_type() {
166         return getRuntime().newString(getJavaClass().getName());
167     }
168
169     public IRubyObject java_class() {
170         return JavaClass.get(getRuntime(), getJavaClass());
171     }
172
173     public RubyFixnum length() {
174         throw getRuntime().newTypeError("not a java array");
175     }
176
177     public IRubyObject aref(IRubyObject index) {
178         throw getRuntime().newTypeError("not a java array");
179     }
180
181     public IRubyObject aset(IRubyObject index, IRubyObject someValue) {
182         throw getRuntime().newTypeError("not a java array");
183     }
184     
185     public IRubyObject afill (IRubyObject beginIndex, IRubyObject endIndex, IRubyObject someValue) {
186         throw getRuntime().newTypeError("not a java array");
187     }
188     
189     public IRubyObject is_java_proxy() {
190         return getRuntime().getTrue();
191     }
192
193     public IRubyObject ruby_synchronized(Block block) {
194         Object JavaDoc lock = getValue();
195         synchronized (lock != null ? lock : NULL_LOCK) {
196             return getRuntime().getCurrentContext().yield(null, block);
197         }
198     }
199 }
200
Popular Tags