Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: EPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Eclipse Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/epl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2002 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net> Copyright (C) 2004-2005 Thomas E Enebo <enebo@acm.org> Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org> Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the EPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the EPL, the GPL or the LGPL. END LICENSE BLOCK ***
  
  package org.jruby.javasupport;
  
  import java.util.HashMap;
  import java.util.Map;
  import java.util.HashSet;
  import java.util.Set;
  
  
  import org.jruby.Ruby;
  import static org.jruby.runtime.Visibility.*;
  import org.jruby.util.*;
 
 @JRubyModule(name = "Java")
 public class Java implements Library {
     public static final boolean NEW_STYLE_EXTENSION = ..load();
     public static final boolean OBJECT_PROXY_CACHE = ..load();
 
     public void load(Ruby runtimeboolean wrapthrows IOException {
         createJavaModule(runtime);
 
         RubyModule jpmt = runtime.defineModule("JavaPackageModuleTemplate");
         jpmt.getSingletonClass().setSuperClass(new BlankSlateWrapper(runtimejpmt.getMetaClass().getSuperClass(), runtime.getKernel()));
 
         runtime.getLoadService().require("jruby/java");
         
         // rewite ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
         RubyClass ajp = runtime.getClass("ArrayJavaProxy");
         ajp.setSuperClass(runtime.getJavaSupport().getObjectJavaClass().getProxyClass());
         ajp.includeModule(runtime.getEnumerable());
         
         RubyClassPathVariable.createClassPathVariable(runtime);
         
         runtime.setJavaProxyClassFactory(JavaProxyClassFactory.createFactory());
 
         // modify ENV_JAVA to be a read/write version
         Map systemProps = new SystemPropertiesMap();
         runtime.getObject().setConstantQuiet(
                 "ENV_JAVA",
                 new MapJavaProxy(
                         runtime,
                         (RubyClass)Java.getProxyClass(runtimeSystemPropertiesMap.class),
                         systemProps));
     }
 
     public static RubyModule createJavaModule(Ruby runtime) {
         ThreadContext context = runtime.getCurrentContext();
         RubyModule javaModule = runtime.defineModule("Java");
         
         javaModule.defineAnnotatedMethods(Java.class);
 
         JavaObject.createJavaObjectClass(runtimejavaModule);
         JavaArray.createJavaArrayClass(runtimejavaModule);
         JavaClass.createJavaClassClass(runtimejavaModule);
         JavaMethod.createJavaMethodClass(runtimejavaModule);
         JavaConstructor.createJavaConstructorClass(runtimejavaModule);
         JavaField.createJavaFieldClass(runtimejavaModule);
         
         // set of utility methods for Java-based proxy objects
         JavaProxyMethods.createJavaProxyMethods(context);
         
         // the proxy (wrapper) type hierarchy
         JavaProxy.createJavaProxy(context);
         ArrayJavaProxyCreator.createArrayJavaProxyCreator(context);
         ConcreteJavaProxy.createConcreteJavaProxy(context);
         InterfaceJavaProxy.createInterfaceJavaProxy(context);
         ArrayJavaProxy.createArrayJavaProxy(context);
 
         // creates ruby's hash methods' proxy for Map interface
         MapJavaProxy.createMapJavaProxy(context);
 
         // also create the JavaProxy* classes
         JavaProxyClass.createJavaProxyModule(runtime);
 
         // The template for interface modules
         JavaInterfaceTemplate.createJavaInterfaceTemplateModule(context);
 
         RubyModule javaUtils = runtime.defineModule("JavaUtilities");
         
         javaUtils.defineAnnotatedMethods(JavaUtilities.class);
 
         JavaArrayUtilities.createJavaArrayUtilitiesModule(runtime);
         
         // Now attach Java-related extras to core classes
         runtime.getArray().defineAnnotatedMethods(ArrayJavaAddons.class);
         runtime.getKernel().defineAnnotatedMethods(KernelJavaAddons.class);
         runtime.getString().defineAnnotatedMethods(StringJavaAddons.class);
         runtime.getIO().defineAnnotatedMethods(IOJavaAddons.class);
 
         if (runtime.getObject().isConstantDefined("StringIO")) {
             ((RubyClass)runtime.getObject().getConstant("StringIO")).defineAnnotatedMethods(IOJavaAddons.AnyIO.class);
         }
         
         // add all name-to-class mappings
         addNameClassMappings(runtimeruntime.getJavaSupport().getNameClassMap());
         
         // add some base Java classes everyone will need
         runtime.getJavaSupport().setObjectJavaClass(JavaClass.get(runtimeObject.class));
 
         return javaModule;
     }
 
     public static class OldStyleExtensionInherited {
         @JRubyMethod
         public static IRubyObject inherited(IRubyObject recvIRubyObject arg0) {
             return Java.concrete_proxy_inherited(recvarg0);
         }
     };
 
     public static class NewStyleExtensionInherited {
         @JRubyMethod
         public static IRubyObject inherited(IRubyObject recvIRubyObject arg0) {
             if (!(arg0 instanceof RubyClass)) {
                 throw recv.getRuntime().newTypeError(arg0recv.getRuntime().getClassClass());
             }
             
             JavaInterfaceTemplate.addRealImplClassNew((RubyClass)arg0);
             return recv.getRuntime().getNil();
         }
     };
    
    
This populates the master map from short-cut names to JavaClass instances for a number of core Java types.

Parameters:
runtime
nameClassMap
 
     private static void addNameClassMappings(Ruby runtimeMap<StringJavaClassnameClassMap) {
         JavaClass booleanPrimClass = JavaClass.get(runtime.);
         JavaClass booleanClass = JavaClass.get(runtimeBoolean.class);
         nameClassMap.put("boolean"booleanPrimClass);
         nameClassMap.put("Boolean"booleanClass);
         nameClassMap.put("java.lang.Boolean"booleanClass);
         
         JavaClass bytePrimClass = JavaClass.get(runtime.);
         JavaClass byteClass = JavaClass.get(runtimeByte.class);
         nameClassMap.put("byte"bytePrimClass);
         nameClassMap.put("Byte"byteClass);
         nameClassMap.put("java.lang.Byte"byteClass);
         
         JavaClass shortPrimClass = JavaClass.get(runtime.);
         JavaClass shortClass = JavaClass.get(runtimeShort.class);
         nameClassMap.put("short"shortPrimClass);
         nameClassMap.put("Short"shortClass);
         nameClassMap.put("java.lang.Short"shortClass);
         
         JavaClass charPrimClass = JavaClass.get(runtime.);
         JavaClass charClass = JavaClass.get(runtimeCharacter.class);
         nameClassMap.put("char"charPrimClass);
         nameClassMap.put("Character"charClass);
         nameClassMap.put("Char"charClass);
         nameClassMap.put("java.lang.Character"charClass);
         
         JavaClass intPrimClass = JavaClass.get(runtime.);
         JavaClass intClass = JavaClass.get(runtimeInteger.class);
         nameClassMap.put("int"intPrimClass);
         nameClassMap.put("Integer"intClass);
         nameClassMap.put("Int"intClass);
         nameClassMap.put("java.lang.Integer"intClass);
         
         JavaClass longPrimClass = JavaClass.get(runtime.);
         JavaClass longClass = JavaClass.get(runtimeLong.class);
         nameClassMap.put("long"longPrimClass);
         nameClassMap.put("Long"longClass);
         nameClassMap.put("java.lang.Long"longClass);
         
         JavaClass floatPrimClass = JavaClass.get(runtime.);
         JavaClass floatClass = JavaClass.get(runtimeFloat.class);
         nameClassMap.put("float"floatPrimClass);
         nameClassMap.put("Float"floatClass);
         nameClassMap.put("java.lang.Float"floatClass);
         
         JavaClass doublePrimClass = JavaClass.get(runtime.);
         JavaClass doubleClass = JavaClass.get(runtimeDouble.class);
         nameClassMap.put("double"doublePrimClass);
         nameClassMap.put("Double"doubleClass);
         nameClassMap.put("java.lang.Double"doubleClass);
         
         JavaClass bigintClass = JavaClass.get(runtimeBigInteger.class);
         nameClassMap.put("big_int"bigintClass);
         nameClassMap.put("big_integer"bigintClass);
         nameClassMap.put("BigInteger"bigintClass);
         nameClassMap.put("java.math.BigInteger"bigintClass);
         
         JavaClass bigdecimalClass = JavaClass.get(runtimeBigDecimal.class);
         nameClassMap.put("big_decimal"bigdecimalClass);
         nameClassMap.put("BigDecimal"bigdecimalClass);
         nameClassMap.put("java.math.BigDecimal"bigdecimalClass);
         
         JavaClass objectClass = JavaClass.get(runtimeObject.class);
         nameClassMap.put("object"objectClass);
         nameClassMap.put("Object"objectClass);
         nameClassMap.put("java.lang.Object"objectClass);
         
         JavaClass stringClass = JavaClass.get(runtimeString.class);
         nameClassMap.put("string"stringClass);
         nameClassMap.put("String"stringClass);
         nameClassMap.put("java.lang.String"stringClass);
     }
 
     private static final ClassProvider JAVA_PACKAGE_CLASS_PROVIDER = new ClassProvider() {
 
         public RubyClass defineClassUnder(RubyModule pkgString nameRubyClass superClazz) {
             // shouldn't happen, but if a superclass is specified, it's not ours
             if (superClazz != null) {
                 return null;
             }
             IRubyObject packageName;
             // again, shouldn't happen. TODO: might want to throw exception instead.
             if ((packageName = pkg.getInstanceVariables().getInstanceVariable("@package_name")) == null) {
                 return null;
             }
             Ruby runtime = pkg.getRuntime();
             return (RubyClassget_proxy_class(
                     runtime.getJavaSupport().getJavaUtilitiesModule(),
                     JavaClass.forNameVerbose(runtimepackageName.asJavaString() + name));
         }
 
         public RubyModule defineModuleUnder(RubyModule pkgString name) {
             IRubyObject packageName;
             // again, shouldn't happen. TODO: might want to throw exception instead.
             if ((packageName = pkg.getInstanceVariables().getInstanceVariable("@package_name")) == null) {
                 return null;
             }
             Ruby runtime = pkg.getRuntime();
             return (RubyModuleget_interface_module(
                     runtime,
                     JavaClass.forNameVerbose(runtimepackageName.asJavaString() + name));
         }
     };
 
     private static final Map<StringBooleanJAVA_PRIMITIVES = new HashMap<StringBoolean>();
     static {
         String[] primitives = {"boolean""byte""char""short""int""long""float""double"};
         for (String primitive : primitives) {
             .put(primitive.);
         }
     }
 
     public static IRubyObject create_proxy_class(
             IRubyObject recv,
             IRubyObject constant,
             IRubyObject javaClass,
             IRubyObject module) {
         Ruby runtime = recv.getRuntime();
 
         if (!(module instanceof RubyModule)) {
             throw runtime.newTypeError(moduleruntime.getModule());
         }
         IRubyObject proxyClass = get_proxy_class(recvjavaClass);
         RubyModule m = (RubyModule)module;
         String constName = constant.asJavaString();
         IRubyObject existing = m.getConstantNoConstMissing(constName);
 
         if (existing != null
                 && existing != .
                 && existing != proxyClass) {
             runtime.getWarnings().warn("replacing " + existing + " with " + proxyClass + " in constant '" + constName + " on class/module " + m);
         }
         
         return ((RubyModulemodule).setConstantQuiet(constant.asJavaString(), get_proxy_class(recvjavaClass));
     }
 
     public static IRubyObject get_java_class(IRubyObject recvIRubyObject name) {
         try {
             return JavaClass.for_name(recvname);
         } catch (Exception e) {
             recv.getRuntime().getJavaSupport().handleNativeException(enull);
             return recv.getRuntime().getNil();
         }
     }

    
Same as Java#getInstance(runtime, rawJavaObject, false).
 
     public static IRubyObject getInstance(Ruby runtimeObject rawJavaObject) {
         return getInstance(runtimerawJavaObjectfalse);
     }
    
    
Returns a new proxy instance of a type corresponding to rawJavaObject's class, or the cached proxy if we've already seen this object. Note that primitives and strings are not coerced to corresponding Ruby types; use JavaUtil.convertJavaToUsableRubyObject to get coerced types or proxies as appropriate.

Parameters:
runtime the JRuby runtime
rawJavaObject the object to get a wrapper for
forceCache whether to force the use of the proxy cache
Returns:
the new (or cached) proxy for the specified Java object
See also:
JavaUtil.convertJavaToUsableRubyObject(org.jruby.Ruby,java.lang.Object)
 
     public static IRubyObject getInstance(Ruby runtimeObject rawJavaObjectboolean forceCache) {
         if (rawJavaObject != null) {
             RubyClass proxyClass = (RubyClassgetProxyClass(runtimerawJavaObject.getClass());
 
             if ( || forceCache || proxyClass.getCacheProxy()) {
                 return runtime.getJavaSupport().getObjectProxyCache().getOrCreate(rawJavaObjectproxyClass);
             } else {
                 return allocateProxy(rawJavaObjectproxyClass);
             }
         }
         return runtime.getNil();
     }
 
     public static RubyModule getInterfaceModule(Ruby runtimeJavaClass javaClass) {
         if (!javaClass.javaClass().isInterface()) {
             throw runtime.newArgumentError(javaClass.toString() + " is not an interface");
         }
         RubyModule interfaceModule;
         if ((interfaceModule = javaClass.getProxyModule()) != null) {
             return interfaceModule;
         }
         javaClass.lockProxy();
         try {
             if ((interfaceModule = javaClass.getProxyModule()) == null) {
                 interfaceModule = (RubyModuleruntime.getJavaSupport().getJavaInterfaceTemplate().dup();
                 interfaceModule.setInstanceVariable("@java_class"javaClass);
                 javaClass.setupInterfaceModule(interfaceModule);
                 // include any interfaces we extend
                 Class<?>[] extended = javaClass.javaClass().getInterfaces();
                 for (int i = extended.length; --i >= 0;) {
                     JavaClass extendedClass = JavaClass.get(runtimeextended[i]);
                     RubyModule extModule = getInterfaceModule(runtimeextendedClass);
                     interfaceModule.includeModule(extModule);
                 }
                 addToJavaPackageModule(interfaceModulejavaClass);
             }
         } finally {
             javaClass.unlockProxy();
         }
         return interfaceModule;
     }
 
     public static IRubyObject get_interface_module(Ruby runtimeIRubyObject javaClassObject) {
         JavaClass javaClass;
         if (javaClassObject instanceof RubyString) {
             javaClass = JavaClass.forNameVerbose(runtimejavaClassObject.asJavaString());
         } else if (javaClassObject instanceof JavaClass) {
             javaClass = (JavaClassjavaClassObject;
         } else {
             throw runtime.newArgumentError("expected JavaClass, got " + javaClassObject);
         }
         return getInterfaceModule(runtimejavaClass);
     }
 
     public static RubyClass getProxyClassForObject(Ruby runtimeObject object) {
         return (RubyClass)getProxyClass(runtimeobject.getClass());
     }
 
     public static RubyModule getProxyClass(Ruby runtimeJavaClass javaClass) {
         return getProxyClass(runtimejavaClass.javaClass());
     }
 
     public static RubyModule getProxyClass(Ruby runtimeClass c) {
         return runtime.getJavaSupport().getProxyClassFromCache(c);
     }
     
     public static RubyModule createProxyClassForClass(Ruby runtimefinal Class c) {
         RubyModule proxyClass;
         JavaClass javaClass = runtime.getJavaSupport().getJavaClassFromCache(c);
         
         if (c.isInterface()) {
             return Java.getInterfaceModule(runtimejavaClass);
         }
         
         javaClass.lockProxy();
         try {
             if ((proxyClass = javaClass.getProxyClass()) == null) {
 
                 if (c.isArray()) {
                     proxyClass = Java.createProxyClass(runtime,
                             runtime.getJavaSupport().getArrayProxyClass(),
                             javaClasstrue);
 
                     // FIXME: Organizationally this might be nicer in a specialized class
                     if (c.getComponentType() == byte.class) {
                         final Encoding ascii8bit = runtime.getEncodingService().getAscii8bitEncoding();
                         
                         // All bytes can be considered raw strings and forced to particular codings if not 8bitascii
                         proxyClass.addMethod("to_s"new JavaMethodZero(proxyClass) {
                             @Override
                             public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString name) {
                                 ByteList bytes = new ByteList((byte[]) ((ArrayJavaProxyself).getObject(), ascii8bit);
                                 return RubyString.newStringLight(context.runtimebytes);
                             }
                         });
                     }   
                 } else if (c.isPrimitive()) {
                     proxyClass = createProxyClass(runtime,
                             runtime.getJavaSupport().getConcreteProxyClass(),
                             javaClasstrue);
 
                 } else if (c == Object.class) {
                     // java.lang.Object is added at root of java proxy classes
                     proxyClass = createProxyClass(runtime,
                             runtime.getJavaSupport().getConcreteProxyClass(),
                             javaClasstrue);
                     if () {
                         proxyClass.getMetaClass().defineAnnotatedMethods(Java.NewStyleExtensionInherited.class);
                     } else {
                         proxyClass.getMetaClass().defineAnnotatedMethods(Java.OldStyleExtensionInherited.class);
                     }
                     addToJavaPackageModule(proxyClassjavaClass);
 
                 } else {
                     // other java proxy classes added under their superclass' java proxy
                     proxyClass = createProxyClass(runtime,
                         (RubyClassgetProxyClass(runtimec.getSuperclass()),
                         javaClassfalse);
                     // include interface modules into the proxy class
                     Class<?>[] interfaces = c.getInterfaces();
                     for (int i = interfaces.length; --i >= 0;) {
                         JavaClass ifc = JavaClass.get(runtimeinterfaces[i]);
                         // java.util.Map type object has its own proxy, but following
                         // is needed. Unless kind_of?(is_a?) test will fail.
                         //if (interfaces[i] != java.util.Map.class) {
                             proxyClass.includeModule(getInterfaceModule(runtimeifc));
                         //}
                     }
                     if (Modifier.isPublic(c.getModifiers())) {
                         addToJavaPackageModule(proxyClassjavaClass);
                     }
                 }
 
                 // JRUBY-1000, fail early when attempting to subclass a final Java class;
                 // solved here by adding an exception-throwing "inherited"
                 if (Modifier.isFinal(c.getModifiers())) {
                     proxyClass.getMetaClass().addMethod("inherited"new org.jruby.internal.runtime.methods.JavaMethod(proxyClass) {
                         @Override
                         public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] argsBlock block) {
                             throw context.runtime.newTypeError("can not extend final Java class: " + c.getCanonicalName());
                         }
                     });
                 }
             }
         } finally {
             javaClass.unlockProxy();
         }
         
         return proxyClass;
     }
 
     public static IRubyObject get_proxy_class(IRubyObject recvIRubyObject java_class_object) {
         Ruby runtime = recv.getRuntime();
         JavaClass javaClass;
         if (java_class_object instanceof RubyString) {
             javaClass = JavaClass.for_name(recvjava_class_object);
         } else if (java_class_object instanceof JavaClass) {
             javaClass = (JavaClassjava_class_object;
         } else {
             throw runtime.newTypeError(java_class_objectruntime.getJavaSupport().getJavaClassClass());
         }
         return getProxyClass(runtimejavaClass);
     }
 
     private static RubyClass createProxyClass(Ruby runtimeRubyClass baseType,
             JavaClass javaClassboolean invokeInherited) {
         // JRUBY-2938 the proxy class might already exist
         RubyClass proxyClass = javaClass.getProxyClass();
         if (proxyClass != nullreturn proxyClass;
 
         // this needs to be split, since conditional calling #inherited doesn't fit standard ruby semantics
         RubyClass.checkInheritable(baseType);
         RubyClass superClass = (RubyClassbaseType;
         proxyClass = RubyClass.newClass(runtimesuperClass);
         proxyClass.makeMetaClass(superClass.getMetaClass());
         try {
             javaClass.javaClass().asSubclass(java.util.Map.class);
             proxyClass.setAllocator(runtime.getJavaSupport().getMapJavaProxyClass().getAllocator());
             proxyClass.defineAnnotatedMethods(MapJavaProxy.class);
             proxyClass.includeModule(runtime.getEnumerable());
         } catch (ClassCastException e) {
             proxyClass.setAllocator(superClass.getAllocator());
         }
         if (invokeInherited) {
             proxyClass.inherit(superClass);
         }
         proxyClass.callMethod(runtime.getCurrentContext(), "java_class="javaClass);
         javaClass.setupProxy(proxyClass);
 
         // add java_method for unbound use
         proxyClass.defineAnnotatedMethods(JavaProxyClassMethods.class);
         return proxyClass;
     }
 
     public static class JavaProxyClassMethods {
         @JRubyMethod(meta = true)
         public static IRubyObject java_method(ThreadContext contextIRubyObject proxyClassIRubyObject rubyName) {
             String name = rubyName.asJavaString();
 
             return getRubyMethod(contextproxyClassname);
         }
 
         @JRubyMethod(meta = true)
         public static IRubyObject java_method(ThreadContext contextIRubyObject proxyClassIRubyObject rubyNameIRubyObject argTypes) {
             String name = rubyName.asJavaString();
             RubyArray argTypesAry = argTypes.convertToArray();
             Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argTypesAry.size()]);
 
             return getRubyMethod(contextproxyClassnameargTypesClasses);
         }
 
         @JRubyMethod(meta = true)
         public static IRubyObject java_send(ThreadContext contextIRubyObject recvIRubyObject rubyName) {
             String name = rubyName.asJavaString();
             Ruby runtime = context.runtime;
 
             JavaMethod method = new JavaMethod(runtimegetMethodFromClass(runtimerecvname));
             return method.invokeStaticDirect();
         }
 
         @JRubyMethod(meta = true)
         public static IRubyObject java_send(ThreadContext contextIRubyObject recvIRubyObject rubyNameIRubyObject argTypes) {
             String name = rubyName.asJavaString();
             RubyArray argTypesAry = argTypes.convertToArray();
             Ruby runtime = context.runtime;
 
             if (argTypesAry.size() != 0) {
                 Class[] argTypesClasses = (Class[]) argTypesAry.toArray(new Class[argTypesAry.size()]);
                 throw JavaMethod.newArgSizeMismatchError(runtimeargTypesClasses);
             }
 
             JavaMethod method = new JavaMethod(runtimegetMethodFromClass(runtimerecvname));
             return method.invokeStaticDirect();
         }
 
         @JRubyMethod(meta = true)
         public static IRubyObject java_send(ThreadContext contextIRubyObject recvIRubyObject rubyNameIRubyObject argTypesIRubyObject arg0) {
             String name = rubyName.asJavaString();
             RubyArray argTypesAry = argTypes.convertToArray();
             Ruby runtime = context.runtime;
 
             if (argTypesAry.size() != 1) {
                 throw JavaMethod.newArgSizeMismatchError(runtime, (ClassargTypesAry.eltInternal(0).toJava(Class.class));
             }
 
             Class argTypeClass = (ClassargTypesAry.eltInternal(0).toJava(Class.class);
 
             JavaMethod method = new JavaMethod(runtimegetMethodFromClass(runtimerecvnameargTypeClass));
             return method.invokeStaticDirect(arg0.toJava(argTypeClass));
         }
 
         @JRubyMethod(required = 4, rest = true, meta = true)
         public static IRubyObject java_send(ThreadContext contextIRubyObject recvIRubyObject[] args) {
             Ruby runtime = context.runtime;
 
             String name = args[0].asJavaString();
             RubyArray argTypesAry = args[1].convertToArray();
             int argsLen = args.length - 2;
 
             if (argTypesAry.size() != argsLen) {
                 throw JavaMethod.newArgSizeMismatchError(runtime, (Class[]) argTypesAry.toArray(new Class[argTypesAry.size()]));
             }
 
             Class[] argTypesClasses = (Class[]) argTypesAry.toArray(new Class[argsLen]);
 
             Object[] argsAry = new Object[argsLen];
             for (int i = 0; i < argsLeni++) {
                 argsAry[i] = args[i + 2].toJava(argTypesClasses[i]);
             }
 
             JavaMethod method = new JavaMethod(runtimegetMethodFromClass(runtimerecvnameargTypesClasses));
             return method.invokeStaticDirect(argsAry);
         }
 
         @JRubyMethod(meta = true, visibility = )
         public static IRubyObject java_alias(ThreadContext contextIRubyObject proxyClassIRubyObject newNameIRubyObject rubyName) {
             return java_alias(contextproxyClassnewNamerubyNamecontext.runtime.newEmptyArray());
         }
 
         @JRubyMethod(meta = true, visibility = )
         public static IRubyObject java_alias(ThreadContext contextIRubyObject proxyClassIRubyObject newNameIRubyObject rubyNameIRubyObject argTypes) {
             String name = rubyName.asJavaString();
             String newNameStr = newName.asJavaString();
             RubyArray argTypesAry = argTypes.convertToArray();
             Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argTypesAry.size()]);
             Ruby runtime = context.runtime;
             RubyClass rubyClass;
 
             if (proxyClass instanceof RubyClass) {
                 rubyClass = (RubyClass)proxyClass;
             } else {
                 throw runtime.newTypeError(proxyClassruntime.getModule());
             }
 
             Method method = getMethodFromClass(runtimeproxyClassnameargTypesClasses);
             MethodInvoker invoker = getMethodInvokerForMethod(rubyClassmethod);
 
             if (Modifier.isStatic(method.getModifiers())) {
                 // add alias to meta
                 rubyClass.getSingletonClass().addMethod(newNameStrinvoker);
             } else {
                 rubyClass.addMethod(newNameStrinvoker);
             }
 
             return runtime.getNil();
         }
     }
 
     private static IRubyObject getRubyMethod(ThreadContext contextIRubyObject proxyClassString nameClass... argTypesClasses) {
         Ruby runtime = context.runtime;
         RubyClass rubyClass;
         
         if (proxyClass instanceof RubyClass) {
             rubyClass = (RubyClass)proxyClass;
         } else {
             throw runtime.newTypeError(proxyClassruntime.getModule());
         }
 
         Method jmethod = getMethodFromClass(runtimeproxyClassnameargTypesClasses);
         String prettyName = name + CodegenUtils.prettyParams(argTypesClasses);
         
         if (Modifier.isStatic(jmethod.getModifiers())) {
             MethodInvoker invoker = new StaticMethodInvoker(rubyClassjmethod);
             return RubyMethod.newMethod(rubyClassprettyNamerubyClassnameinvokerproxyClass);
         } else {
             MethodInvoker invoker = new InstanceMethodInvoker(rubyClassjmethod);
             return RubyUnboundMethod.newUnboundMethod(rubyClassprettyNamerubyClassnameinvoker);
         }
     }
 
     public static Method getMethodFromClass(Ruby runtimeIRubyObject proxyClassString nameClass... argTypes) {
         Class jclass = (Class)((JavaClass)proxyClass.callMethod(runtime.getCurrentContext(), "java_class")).getValue();
 
         try {
             return jclass.getMethod(nameargTypes);
         } catch (NoSuchMethodException nsme) {
             String prettyName = name + CodegenUtils.prettyParams(argTypes);
             String errorName = jclass.getName() + "." + prettyName;
             throw runtime.newNameError("Java method not found: " + errorNamename);
         }
     }
 
     private static MethodInvoker getMethodInvokerForMethod(RubyClass metaClassMethod method) {
         if (Modifier.isStatic(method.getModifiers())) {
             return new StaticMethodInvoker(metaClass.getMetaClass(), method);
         } else {
             return new InstanceMethodInvoker(metaClassmethod);
         }
     }
 
     public static IRubyObject concrete_proxy_inherited(IRubyObject recvIRubyObject subclass) {
         Ruby runtime = recv.getRuntime();
         ThreadContext tc = runtime.getCurrentContext();
         JavaSupport javaSupport = runtime.getJavaSupport();
         RubyClass javaProxyClass = javaSupport.getJavaProxyClass().getMetaClass();
         Helpers.invokeAs(tcjavaProxyClassrecv"inherited"subclass,
                 .);
         return setupJavaSubclass(tcsubclassrecv.callMethod(tc"java_class"));
     }
 
     private static IRubyObject setupJavaSubclass(ThreadContext contextIRubyObject subclassIRubyObject java_class) {
         final Ruby runtime = context.runtime;
 
         if (!(subclass instanceof RubyClass)) {
             throw runtime.newTypeError(subclassruntime.getClassClass());
         }
         RubyClass rubySubclass = (RubyClass)subclass;
         rubySubclass.getInstanceVariables().setInstanceVariable("@java_proxy_class"runtime.getNil());
 
         // Subclasses of Java classes can safely use ivars, so we set this to silence warnings
         rubySubclass.setCacheProxy(true);
 
         RubyClass subclassSingleton = rubySubclass.getSingletonClass();
         subclassSingleton.addReadWriteAttribute(context"java_proxy_class");
         subclassSingleton.addMethod("java_interfaces"new JavaMethodZero(subclassSingleton) {
             @Override
             public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString name) {
                 IRubyObject javaInterfaces = self.getInstanceVariables().getInstanceVariable("@java_interfaces");
                 if (javaInterfaces != nullreturn javaInterfaces.dup();
                 return context.runtime.getNil();
             }
         });
 
         rubySubclass.addMethod("__jcreate!"new JavaMethodN(subclassSingleton) {
             private final Map<IntegerParameterTypesmethodCache = new HashMap<IntegerParameterTypes>();
             @Override
             public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] args) {
                 IRubyObject proxyClass = self.getMetaClass().getInstanceVariables().getInstanceVariable("@java_proxy_class");
                 if (proxyClass == null || proxyClass.isNil()) {
                     proxyClass = JavaProxyClass.get_with_class(selfself.getMetaClass());
                     self.getMetaClass().getInstanceVariables().setInstanceVariable("@java_proxy_class"proxyClass);
                 }
                 
                 JavaProxyClass realProxyClass = (JavaProxyClass)proxyClass;
                 RubyArray constructors = realProxyClass.constructors();
                 ArrayList<JavaProxyConstructorforArity = new ArrayList<JavaProxyConstructor>();
                 for (int i = 0; i < constructors.size(); i++) {
                     JavaProxyConstructor constructor = (JavaProxyConstructor)constructors.eltInternal(i);
                     if (constructor.getParameterTypes().length == args.length) {
                         forArity.add(constructor);
                     }
                 }
                 
                 if (forArity.size() == 0) {
                     throw runtime.newArgumentError("wrong number of arguments for constructor");
                 }
 
                 JavaProxyConstructor matching = (JavaProxyConstructor)CallableSelector.matchingCallableArityN(
                         runtime,
                         forArity.toArray(new JavaProxyConstructor[forArity.size()]), argsargs.length);
 
                 if (matching == null) {
                     throw runtime.newArgumentError("wrong number of arguments for constructor");
                 }
 
                 Object[] newArgs = new Object[args.length];
                 Class[] parameterTypes = matching.getParameterTypes();
                 for (int i = 0; i < args.lengthi++) {
                     newArgs[i] = args[i].toJava(parameterTypes[i]);
                 }
                 
                 JavaObject newObject = matching.newInstance(selfnewArgs);
                 return JavaUtilities.set_java_object(selfselfnewObject);
             }
         });
 
         return runtime.getNil();
     }
 
     // package scheme 2: separate module for each full package name, constructed 
     // from the camel-cased package segments: Java::JavaLang::Object, 
     private static void addToJavaPackageModule(RubyModule proxyClassJavaClass javaClass) {
         Ruby runtime = proxyClass.getRuntime();
         Class<?> clazz = javaClass.javaClass();
         String fullName;
         if ((fullName = clazz.getName()) == null) {
             return;
         }
         int endPackage = fullName.lastIndexOf('.');
         RubyModule parentModule;
         String className;
 
         // inner classes must be nested
         if (fullName.indexOf('$') != -1) {
             IRubyObject declClass = javaClass.declaring_class();
             if (declClass.isNil()) {
                 // no containing class for a $ class; treat it as internal and don't define a constant
                 return;
             }
             parentModule = getProxyClass(runtime, (JavaClass)declClass);
             className = clazz.getSimpleName();
         } else {
             String packageString = endPackage < 0 ? "" : fullName.substring(0, endPackage);
             parentModule = getJavaPackageModule(runtimepackageString);
             className = parentModule == null ? fullName : fullName.substring(endPackage + 1);
         }
         
         if (parentModule != null && IdUtil.isConstant(className)) {
             if (parentModule.getConstantAt(className) == null) {
                 parentModule.setConstant(classNameproxyClass);
             }
         }
     }
 
     public static RubyModule getJavaPackageModule(Ruby runtimePackage pkg) {
         return pkg == null ?
                 getJavaPackageModule(runtime"") :
                 getJavaPackageModule(runtimepkg.getName());
     }
 
     private static RubyModule getJavaPackageModule(Ruby runtimeString packageString) {
         String packageName;
         int length = packageString.length();
         if (length == 0) {
             packageName = "Default";
         } else {
             StringBuilder buf = new StringBuilder();
             for (int start = 0, offset = 0; start < lengthstart = offset + 1) {
                 if ((offset = packageString.indexOf('.'start)) == -1) {
                     offset = length;
                 }
                 buf.append(Character.toUpperCase(packageString.charAt(start))).append(packageString.substring(start + 1, offset));
             }
             packageName = buf.toString();
         }
 
         RubyModule javaModule = runtime.getJavaSupport().getJavaModule();
         IRubyObject packageModule = javaModule.getConstantAt(packageName);
         if (packageModule == null) {
             return createPackageModule(javaModulepackageNamepackageString);
         } else if (packageModule instanceof RubyModule) {
             return (RubyModulepackageModule;
         } else {
             return null;
         }
     }
 
     private static RubyModule createPackageModule(RubyModule parentString nameString packageString) {
         Ruby runtime = parent.getRuntime();
         RubyModule packageModule = (RubyModuleruntime.getJavaSupport().getPackageModuleTemplate().dup();
         packageModule.setInstanceVariable("@package_name"runtime.newString(
                 packageString.length() > 0 ? packageString + '.' : packageString));
 
         // this is where we'll get connected when classes are opened using
         // package module syntax.
         packageModule.addClassProvider();
 
         parent.const_set(runtime.newSymbol(name), packageModule);
         MetaClass metaClass = (MetaClasspackageModule.getMetaClass();
         metaClass.setAttached(packageModule);
         return packageModule;
     }
     private static final Pattern CAMEL_CASE_PACKAGE_SPLITTER = Pattern.compile("([a-z][0-9]*)([A-Z])");
 
     private static RubyModule getPackageModule(Ruby runtimeString name) {
         RubyModule javaModule = runtime.getJavaSupport().getJavaModule();
         IRubyObject value;
         if ((value = javaModule.getConstantAt(name)) instanceof RubyModule) {
             return (RubyModulevalue;
         }
         String packageName;
         if ("Default".equals(name)) {
             packageName = "";
         } else {
             Matcher m = .matcher(name);
             packageName = m.replaceAll("$1.$2").toLowerCase();
         }
         return createPackageModule(javaModulenamepackageName);
     }
 
     public static IRubyObject get_package_module(IRubyObject recvIRubyObject symObject) {
         return getPackageModule(recv.getRuntime(), symObject.asJavaString());
     }
 
     public static IRubyObject get_package_module_dot_format(IRubyObject recvIRubyObject dottedName) {
         Ruby runtime = recv.getRuntime();
         RubyModule module = getJavaPackageModule(runtimedottedName.asJavaString());
         return module == null ? runtime.getNil() : module;
     }
 
     private static RubyModule getProxyOrPackageUnderPackage(ThreadContext contextfinal Ruby runtime,
             RubyModule parentPackageString sym) {
         IRubyObject packageNameObj = parentPackage.getInstanceVariable("@package_name");
         if (packageNameObj == null) {
             throw runtime.newArgumentError("invalid package module");
         }
         String packageName = packageNameObj.asJavaString();
         final String name = sym.trim().intern();
         if (name.length() == 0) {
             throw runtime.newArgumentError("empty class or package name");
         }
         String fullName = packageName + name;
         if (!Character.isUpperCase(name.charAt(0))) {
             // filter out any Java primitive names
             // TODO: should check against all Java reserved names here, not just primitives
             if (.containsKey(name)) {
                 throw runtime.newArgumentError("illegal package name component: " + name);
             }
             
             // this covers the rare case of lower-case class names (and thus will
             // fail 99.999% of the time). fortunately, we'll only do this once per
             // package name. (and seriously, folks, look into best practices...)
             IRubyObject previousErrorInfo = Helpers.getErrorInfo(runtime);
             try {
                 return getProxyClass(runtimeruntime.getJavaSupport().loadJavaClassQuiet(fullName));
             } catch (RaiseException re) { /* expected */
                 RubyException rubyEx = re.getException();
                 if (rubyEx.kind_of_p(contextruntime.getStandardError()).isTrue()) {
                     Helpers.setErrorInfo(runtimepreviousErrorInfo);
                 }
             } catch (Exception e) { /* expected */ }
 
             // Haven't found a class, continue on as though it were a package
             final RubyModule packageModule = getJavaPackageModule(runtimefullName);
             // TODO: decompose getJavaPackageModule so we don't parse fullName