001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
015: * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
016: * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
017: * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
018: * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
019: * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * either of the GNU General Public License Version 2 or later (the "GPL"),
023: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
024: * in which case the provisions of the GPL or the LGPL are applicable instead
025: * of those above. If you wish to allow use of your version of this file only
026: * under the terms of either the GPL or the LGPL, and not to allow others to
027: * use your version of this file under the terms of the CPL, indicate your
028: * decision by deleting the provisions above and replace them with the notice
029: * and other provisions required by the GPL or the LGPL. If you do not delete
030: * the provisions above, a recipient may use your version of this file under
031: * the terms of any one of the CPL, the GPL or the LGPL.
032: ***** END LICENSE BLOCK *****/package org.jruby.javasupport;
033:
034: import java.lang.ref.WeakReference;
035: import java.net.URL;
036: import java.util.Collections;
037: import java.util.HashMap;
038: import java.util.Map;
039:
040: import org.jruby.Ruby;
041: import org.jruby.RubyClass;
042: import org.jruby.RubyModule;
043: import org.jruby.RubyProc;
044: import org.jruby.util.WeakIdentityHashMap;
045: import org.jruby.util.JRubyClassLoader;
046: import org.jruby.exceptions.RaiseException;
047: import org.jruby.runtime.builtin.IRubyObject;
048:
049: public class JavaSupport {
050: private Ruby runtime;
051:
052: private Map exceptionHandlers = new HashMap();
053:
054: private JRubyClassLoader javaClassLoader;
055:
056: private Map instanceCache = Collections
057: .synchronizedMap(new WeakIdentityHashMap(100));
058:
059: private RubyModule javaModule;
060: private RubyModule javaUtilitiesModule;
061: private RubyClass javaObjectClass;
062: private RubyClass javaClassClass;
063: private RubyClass javaArrayClass;
064: private RubyClass javaProxyClass;
065: private RubyModule javaInterfaceTemplate;
066: private RubyModule packageModuleTemplate;
067: private RubyClass arrayProxyClass;
068: private RubyClass concreteProxyClass;
069:
070: public JavaSupport(Ruby ruby) {
071: this .runtime = ruby;
072: this .javaClassLoader = ruby.getJRubyClassLoader();
073: }
074:
075: public Class loadJavaClass(String className) {
076: try {
077: Class result = primitiveClass(className);
078: if (result == null) {
079: return (Ruby.isSecurityRestricted()) ? Class
080: .forName(className) : Class.forName(className,
081: true, javaClassLoader);
082: }
083: return result;
084: } catch (ClassNotFoundException cnfExcptn) {
085: throw runtime.newNameError("cannot load Java class "
086: + className, className);
087: }
088: }
089:
090: public JavaClass getJavaClassFromCache(Class clazz) {
091: WeakReference ref = (WeakReference) instanceCache.get(clazz);
092:
093: return ref == null ? null : (JavaClass) ref.get();
094: }
095:
096: public void putJavaClassIntoCache(JavaClass clazz) {
097: instanceCache.put(clazz.javaClass(), new WeakReference(clazz));
098: }
099:
100: public void addToClasspath(URL url) {
101: // javaClassLoader = URLClassLoader.newInstance(new URL[] { url }, javaClassLoader);
102: javaClassLoader.addURL(url);
103: }
104:
105: public void defineExceptionHandler(String exceptionClass,
106: RubyProc handler) {
107: exceptionHandlers.put(exceptionClass, handler);
108: }
109:
110: public void handleNativeException(Throwable exception) {
111: if (exception instanceof RaiseException) {
112: throw (RaiseException) exception;
113: }
114: Class excptnClass = exception.getClass();
115: RubyProc handler = (RubyProc) exceptionHandlers.get(excptnClass
116: .getName());
117: while (handler == null && excptnClass != Throwable.class) {
118: excptnClass = excptnClass.getSuperclass();
119: }
120: if (handler != null) {
121: handler.call(new IRubyObject[] { JavaUtil
122: .convertJavaToRuby(runtime, exception) });
123: } else {
124: throw createRaiseException(exception);
125: }
126: }
127:
128: private RaiseException createRaiseException(Throwable exception) {
129: RaiseException re = RaiseException.createNativeRaiseException(
130: runtime, exception);
131:
132: return re;
133: }
134:
135: private static Class primitiveClass(String name) {
136: if (name.equals("long")) {
137: return Long.TYPE;
138: } else if (name.equals("int")) {
139: return Integer.TYPE;
140: } else if (name.equals("boolean")) {
141: return Boolean.TYPE;
142: } else if (name.equals("char")) {
143: return Character.TYPE;
144: } else if (name.equals("short")) {
145: return Short.TYPE;
146: } else if (name.equals("byte")) {
147: return Byte.TYPE;
148: } else if (name.equals("float")) {
149: return Float.TYPE;
150: } else if (name.equals("double")) {
151: return Double.TYPE;
152: }
153: return null;
154: }
155:
156: public ClassLoader getJavaClassLoader() {
157: return javaClassLoader;
158: }
159:
160: public JavaObject getJavaObjectFromCache(Object object) {
161: WeakReference ref = (WeakReference) instanceCache.get(object);
162: if (ref == null) {
163: return null;
164: }
165: JavaObject javaObject = (JavaObject) ref.get();
166: if (javaObject != null && javaObject.getValue() == object) {
167: return javaObject;
168: }
169: return null;
170: }
171:
172: public void putJavaObjectIntoCache(JavaObject object) {
173: instanceCache.put(object.getValue(), new WeakReference(object));
174: }
175:
176: // not synchronizing these methods, no harm if these values get set twice...
177:
178: public RubyModule getJavaModule() {
179: if (javaModule == null) {
180: javaModule = runtime.getModule("Java");
181: }
182: return javaModule;
183: }
184:
185: public RubyModule getJavaUtilitiesModule() {
186: if (javaUtilitiesModule == null) {
187: javaUtilitiesModule = runtime.getModule("JavaUtilities");
188: }
189: return javaUtilitiesModule;
190: }
191:
192: public RubyClass getJavaObjectClass() {
193: if (javaObjectClass == null) {
194: javaObjectClass = getJavaModule().getClass("JavaObject");
195: }
196: return javaObjectClass;
197: }
198:
199: public RubyClass getJavaArrayClass() {
200: if (javaArrayClass == null) {
201: javaArrayClass = getJavaModule().getClass("JavaArray");
202: }
203: return javaArrayClass;
204: }
205:
206: public RubyClass getJavaClassClass() {
207: if (javaClassClass == null) {
208: javaClassClass = getJavaModule().getClass("JavaClass");
209: }
210: return javaClassClass;
211: }
212:
213: public RubyModule getJavaInterfaceTemplate() {
214: if (javaInterfaceTemplate == null) {
215: javaInterfaceTemplate = runtime
216: .getModule("JavaInterfaceTemplate");
217: }
218: return javaInterfaceTemplate;
219: }
220:
221: public RubyModule getPackageModuleTemplate() {
222: if (packageModuleTemplate == null) {
223: packageModuleTemplate = runtime
224: .getModule("JavaPackageModuleTemplate");
225: }
226: return packageModuleTemplate;
227: }
228:
229: public RubyClass getJavaProxyClass() {
230: if (javaProxyClass == null) {
231: javaProxyClass = runtime.getClass("JavaProxy");
232: }
233: return javaProxyClass;
234: }
235:
236: public RubyClass getConcreteProxyClass() {
237: if (concreteProxyClass == null) {
238: concreteProxyClass = runtime.getClass("ConcreteJavaProxy");
239: }
240: return concreteProxyClass;
241: }
242:
243: public RubyClass getArrayProxyClass() {
244: if (arrayProxyClass == null) {
245: arrayProxyClass = runtime.getClass("ArrayJavaProxy");
246: }
247: return arrayProxyClass;
248: }
249:
250: }
|