1 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 51 public class JavaObject extends RubyObject { 52 private static Object NULL_LOCK = new Object (); 53 private final Object value; 54 55 protected JavaObject(Ruby runtime, RubyClass rubyClass, Object value) { 56 super(runtime, rubyClass); 57 this.value = value; 58 } 59 60 protected JavaObject(Ruby runtime, Object value) { 61 this(runtime, runtime.getModule("Java").getClass("JavaObject"), value); 62 } 63 64 public static JavaObject wrap(Ruby runtime, Object value) { 65 Object 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 .class)) { 75 wrapper = JavaClass.get(runtime, (Class )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 getJavaClass() { 86 return value != null ? value.getClass() : Void.TYPE; 87 } 88 89 public Object getValue() { 90 return value; 91 } 92 93 public static RubyClass createJavaObjectClass(Ruby runtime, RubyModule javaModule) { 94 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 lock = getValue(); 195 synchronized (lock != null ? lock : NULL_LOCK) { 196 return getRuntime().getCurrentContext().yield(null, block); 197 } 198 } 199 } 200 | Popular Tags |