KickJava   Java API By Example, From Geeks To Geeks.

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


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) 2002 Jan Arne Petersen <jpetersen@uni-bonn.de>
15  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
16  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
17  * Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
18  * Copyright (C) 2004-2005 Thomas E Enebo <enebo@acm.org>
19  * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * either of the GNU General Public License Version 2 or later (the "GPL"),
23  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
24  * in which case the provisions of the GPL or the LGPL are applicable instead
25  * of those above. If you wish to allow use of your version of this file only
26  * under the terms of either the GPL or the LGPL, and not to allow others to
27  * use your version of this file under the terms of the CPL, indicate your
28  * decision by deleting the provisions above and replace them with the notice
29  * and other provisions required by the GPL or the LGPL. If you do not delete
30  * the provisions above, a recipient may use your version of this file under
31  * the terms of any one of the CPL, the GPL or the LGPL.
32  ***** END LICENSE BLOCK *****/

33 package org.jruby.javasupport;
34
35 import java.lang.reflect.InvocationHandler JavaDoc;
36 import java.lang.reflect.Method JavaDoc;
37 import java.lang.reflect.Proxy JavaDoc;
38 import org.jruby.Ruby;
39 import org.jruby.RubyBignum;
40 import org.jruby.RubyFixnum;
41 import org.jruby.RubyFloat;
42 import org.jruby.RubyModule;
43 import org.jruby.RubyProc;
44 import org.jruby.RubyString;
45 import org.jruby.RubyTime;
46 import org.jruby.javasupport.proxy.JavaProxyClass;
47 import org.jruby.runtime.Block;
48 import org.jruby.runtime.CallbackFactory;
49 import org.jruby.runtime.ClassIndex;
50 import org.jruby.runtime.builtin.IRubyObject;
51
52 public class Java {
53     public static RubyModule createJavaModule(Ruby runtime) {
54         RubyModule javaModule = runtime.defineModule("Java");
55         CallbackFactory callbackFactory = runtime.callbackFactory(Java.class);
56         javaModule.defineModuleFunction("define_exception_handler", callbackFactory.getOptSingletonMethod("define_exception_handler"));
57         javaModule.defineModuleFunction("primitive_to_java", callbackFactory.getSingletonMethod("primitive_to_java", IRubyObject.class));
58         javaModule.defineModuleFunction("java_to_primitive", callbackFactory.getSingletonMethod("java_to_primitive", IRubyObject.class));
59         javaModule.defineModuleFunction("java_to_ruby", callbackFactory.getSingletonMethod("java_to_ruby", IRubyObject.class));
60         javaModule.defineModuleFunction("ruby_to_java", callbackFactory.getSingletonMethod("ruby_to_java", IRubyObject.class));
61         javaModule.defineModuleFunction("new_proxy_instance", callbackFactory.getOptSingletonMethod("new_proxy_instance"));
62
63         JavaObject.createJavaObjectClass(runtime, javaModule);
64         JavaArray.createJavaArrayClass(runtime, javaModule);
65         JavaClass.createJavaClassClass(runtime, javaModule);
66         JavaMethod.createJavaMethodClass(runtime, javaModule);
67         JavaConstructor.createJavaConstructorClass(runtime, javaModule);
68         JavaField.createJavaFieldClass(runtime, javaModule);
69        
70         // also create the JavaProxy* classes
71
JavaProxyClass.createJavaProxyModule(runtime);
72         
73         return javaModule;
74     }
75
76     // Java methods
77
public static IRubyObject define_exception_handler(IRubyObject recv, IRubyObject[] args, Block block) {
78         String JavaDoc name = args[0].toString();
79         RubyProc handler = null;
80         if (args.length > 1) {
81             handler = (RubyProc)args[1];
82         } else {
83             handler = recv.getRuntime().newProc(false, block);
84         }
85         recv.getRuntime().getJavaSupport().defineExceptionHandler(name, handler);
86
87         return recv;
88     }
89
90     public static IRubyObject primitive_to_java(IRubyObject recv, IRubyObject object, Block unusedBlock) {
91         if (object instanceof JavaObject) {
92             return object;
93         }
94         Ruby runtime = recv.getRuntime();
95         Object JavaDoc javaObject;
96         switch (object.getMetaClass().index) {
97         case ClassIndex.NIL:
98             javaObject = null;
99             break;
100         case ClassIndex.FIXNUM:
101             javaObject = new Long JavaDoc(((RubyFixnum) object).getLongValue());
102             break;
103         case ClassIndex.BIGNUM:
104             javaObject = ((RubyBignum) object).getValue();
105             break;
106         case ClassIndex.FLOAT:
107             javaObject = new Double JavaDoc(((RubyFloat) object).getValue());
108             break;
109         case ClassIndex.STRING:
110             javaObject = ((RubyString) object).toString();
111             break;
112         case ClassIndex.TRUE:
113             javaObject = Boolean.TRUE;
114             break;
115         case ClassIndex.FALSE:
116             javaObject = Boolean.FALSE;
117             break;
118         default:
119             if (object instanceof RubyTime) {
120                 javaObject = ((RubyTime)object).getJavaDate();
121             } else {
122                 javaObject = object;
123             }
124         }
125         return JavaObject.wrap(runtime, javaObject);
126     }
127
128     /**
129      * High-level object conversion utility function 'java_to_primitive' is the low-level version
130      */

131     public static IRubyObject java_to_ruby(IRubyObject recv, IRubyObject object, Block unusedBlock) {
132         if (object instanceof JavaObject) {
133             object = JavaUtil.convertJavaToRuby(recv.getRuntime(), ((JavaObject) object).getValue());
134         }
135
136         //if (object.isKindOf(recv.getRuntime().getModule("Java").getClass("JavaObject"))) {
137
if (object instanceof JavaObject) {
138             return recv.getRuntime().getModule("JavaUtilities").callMethod(recv.getRuntime().getCurrentContext(), "wrap", object);
139         }
140
141         return object;
142     }
143
144     // TODO: Formalize conversion mechanisms between Java and Ruby
145
/**
146      * High-level object conversion utility.
147      */

148     public static IRubyObject ruby_to_java(final IRubyObject recv, IRubyObject object, Block unusedBlock) {
149         if (object.respondsTo("to_java_object")) {
150             IRubyObject result = object.getInstanceVariable("@java_object");
151             if (result == null) {
152             result = object.callMethod(recv.getRuntime().getCurrentContext(), "to_java_object");
153             }
154             return result;
155         }
156         
157         return primitive_to_java(recv, object, unusedBlock);
158     }
159
160     public static IRubyObject java_to_primitive(IRubyObject recv, IRubyObject object, Block unusedBlock) {
161         if (object instanceof JavaObject) {
162             return JavaUtil.convertJavaToRuby(recv.getRuntime(), ((JavaObject) object).getValue());
163         }
164
165         return object;
166     }
167
168     public static IRubyObject new_proxy_instance(final IRubyObject recv, IRubyObject[] args, Block block) {
169         int size = recv.checkArgumentCount(args, 1, -1) - 1;
170         final RubyProc proc;
171
172         // Is there a supplied proc argument or do we assume a block was supplied
173
if (args[size] instanceof RubyProc) {
174             proc = (RubyProc) args[size];
175         } else {
176             proc = recv.getRuntime().newProc(false, block);
177             size++;
178         }
179         
180         // Create list of interfaces to proxy (and make sure they really are interfaces)
181
Class JavaDoc[] interfaces = new Class JavaDoc[size];
182         for (int i = 0; i < size; i++) {
183             if (!(args[i] instanceof JavaClass) || !((JavaClass)args[i]).interface_p().isTrue()) {
184                 throw recv.getRuntime().newArgumentError("Java interface expected.");
185             }
186             interfaces[i] = ((JavaClass) args[i]).javaClass();
187         }
188         
189         return JavaObject.wrap(recv.getRuntime(), Proxy.newProxyInstance(recv.getRuntime().getJavaSupport().getJavaClassLoader(), interfaces, new InvocationHandler JavaDoc() {
190             public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] nargs) throws Throwable JavaDoc {
191                 int methodArgsLength = method.getParameterTypes().length;
192                 String JavaDoc methodName = method.getName();
193                 
194                 if (methodName.equals("toString") && methodArgsLength == 0) {
195                     return proxy.getClass().getName();
196                 } else if (methodName.equals("hashCode") && methodArgsLength == 0) {
197                     return new Integer JavaDoc(proxy.getClass().hashCode());
198                 } else if (methodName.equals("equals") && methodArgsLength == 1 && method.getParameterTypes()[0].equals(Object JavaDoc.class)) {
199                     return Boolean.valueOf(proxy == nargs[0]);
200                 }
201                 int length = nargs == null ? 0 : nargs.length;
202                 IRubyObject[] rubyArgs = new IRubyObject[length + 2];
203                 rubyArgs[0] = JavaObject.wrap(recv.getRuntime(), proxy);
204                 rubyArgs[1] = new JavaMethod(recv.getRuntime(), method);
205                 for (int i = 0; i < length; i++) {
206                     rubyArgs[i + 2] = JavaObject.wrap(recv.getRuntime(), nargs[i]);
207                 }
208                 return JavaUtil.convertArgument(proc.call(rubyArgs), method.getReturnType());
209             }
210         }));
211     }
212 }
213
Popular Tags