Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.java.proxies;
  
  import org.jruby.Ruby;
 
 public class JavaInterfaceTemplate {
     public static RubyModule createJavaInterfaceTemplateModule(ThreadContext context) {
         Ruby runtime = context.runtime;
         RubyModule javaInterfaceTemplate = runtime.defineModule("JavaInterfaceTemplate");
 
         RubyClass singleton = javaInterfaceTemplate.getSingletonClass();
         singleton.addReadAttribute(context"java_class");
         singleton.defineAnnotatedMethods(JavaInterfaceTemplate.class);
 
         return javaInterfaceTemplate;
     }
 
     // not intended to be called directly by users (private)
     // OLD TODO from Ruby code:
     // This should be implemented in JavaClass.java, where we can
     // check for reserved Ruby names, conflicting methods, etc.
     @JRubyMethod(visibility = .)
     public static IRubyObject implement(ThreadContext contextIRubyObject selfIRubyObject clazz) {
         Ruby runtime = context.runtime;
 
         if (!(clazz instanceof RubyModule)) {
             throw runtime.newTypeError(clazzruntime.getModule());
         }
 
         RubyModule targetModule = (RubyModule)clazz;
         JavaClass javaClass = (JavaClass)self.getInstanceVariables().getInstanceVariable("@java_class");
         
         Method[] javaInstanceMethods = javaClass.javaClass().getMethods();
         DynamicMethod dummyMethod = new org.jruby.internal.runtime.methods.JavaMethod(targetModule.) {
             @Override
             public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] argsBlock block) {
                 // dummy bodies for default impls
                 return context.runtime.getNil();
             }
         };
         
         for (int i = 0; i < javaInstanceMethods.lengthi++) {
             Method method = javaInstanceMethods[i];
             String name = method.getName();
             if (targetModule.searchMethod(name) != .continue;
             
             targetModule.addMethod(namedummyMethod);
         }
         
         return runtime.getNil();
     }
 
     // framed for invokeSuper
     @JRubyMethod(frame = true)
     public static IRubyObject append_features(ThreadContext contextIRubyObject selfIRubyObject clazzBlock block) {
         if (clazz instanceof RubyClass) {
             appendFeaturesToClass(contextself, (RubyClass)clazz);
         } else if (clazz instanceof RubyModule) {
             appendFeaturesToModule(contextself, (RubyModule)clazz);
         } else {
             throw context.runtime.newTypeError("received " + clazz + ", expected Class/Module");
         }
 
         return RuntimeHelpers.invokeSuper(contextselfclazzblock);
     }
 
     private static void appendFeaturesToClass(ThreadContext contextIRubyObject selffinal RubyClass clazz) {
         Ruby runtime = context.runtime;
         checkAlreadyReified(clazzruntime);
 
         IRubyObject javaClassObj = RuntimeHelpers.getInstanceVariable(selfruntime"@java_class");
         IRubyObject javaInterfaces;
         if (!clazz.hasInstanceVariable("@java_interfaces")) {
             javaInterfaces = RubyArray.newArray(runtimejavaClassObj);
             RuntimeHelpers.setInstanceVariable(javaInterfacesclazz"@java_interfaces");
            initInterfaceImplMethods(contextclazz);
        } else {
            javaInterfaces = RuntimeHelpers.getInstanceVariable(clazzruntime"@java_interfaces");
            // we've already done the above priming logic, just add another interface
            // to the list of intentions unless we're past the point of no return or
            // already intend to implement the given interface
            if (!(javaInterfaces.isFrozen() || ((RubyArray)javaInterfaces).includes(contextjavaClassObj))) {
                ((RubyArray)javaInterfaces).append(javaClassObj);
            }
        }
    }
    private static void checkAlreadyReified(final RubyClass clazzRuby runtimethrows RaiseException {
        // not allowed for original (non-generated) Java classes
        // note: not allowing for any previously created class right now;
        // this restriction might be loosened later for generated classes
        if ((. && clazz.getReifiedClass() != null)
                ||
                (clazz.hasInstanceVariable("@java_class")
                    && clazz.getInstanceVariable("@java_class").isTrue()
                    && !clazz.getSingletonClass().isMethodBound("java_proxy_class"false))
                ||
                (clazz.hasInstanceVariable("@java_proxy_class")
                    && clazz.getInstanceVariable("@java_proxy_class").isTrue())) {
            throw runtime.newArgumentError("can not add Java interface to existing Java class");
        }
    }
    private static void initInterfaceImplMethods(ThreadContext contextRubyClass clazz) {
        // setup new, etc unless this is a ConcreteJavaProxy subclass
        // For JRUBY-4571, check both these, since JavaProxy extension stuff adds the former and this code adds the latter
        if (!(clazz.isMethodBound("__jcreate!"false) || clazz.isMethodBound("__jcreate_meta!"false))) {
            // First we make modifications to the class, to adapt it to being
            // both a Ruby class and a proxy for a Java type
            RubyClass singleton = clazz.getSingletonClass();
            // list of interfaces we implement
            singleton.addReadAttribute(context"java_interfaces");
            if (
                    (!. && clazz.getSuperClass().getRealClass().hasInstanceVariable("@java_class"))
                    || .) {
                // superclass is a Java class...use old style impl for now
                // The replacement "new" allocates and inits the Ruby object as before, but
                // also instantiates our proxified Java object by calling __jcreate!
                final ObjectAllocator proxyAllocator = clazz.getAllocator();
                clazz.setAllocator(new ObjectAllocator() {
                    public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
                        IRubyObject newObj = proxyAllocator.allocate(runtimeklazz);
                        RuntimeHelpers.invoke(runtime.getCurrentContext(), newObj"__jcreate!");
                        return newObj;
                    }
                });
                // jcreate instantiates the proxy object which implements all interfaces
                // and which is wrapped and implemented by this object
                clazz.addMethod("__jcreate!"new JavaMethodN(clazz.) {
                    @Override
                    public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] args) {
                        return jcreateProxy(self);
                    }
                });
            } else {
                // The new "new" actually generates a real Java class to use for the Ruby class's
                // backing store, instantiates that, and then calls initialize on it.
                addRealImplClassNew(clazz);
            }
            // Next, we define a few private methods that we'll use to manipulate
            // the Java object contained within this Ruby object
            // Used by our duck-typification of Proc into interface types, to allow
            // coercing a simple proc into an interface parameter.
            clazz.addMethod("__jcreate_meta!"new JavaMethodN(clazz.) {
                @Override
                public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] args) {
                    IRubyObject result = jcreateProxy(self);
                    return result;
                }
            });
            // If we hold a Java object, we need a java_class accessor
            clazz.addMethod("java_class"new JavaMethodZero(clazz.) {
                @Override
                public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString name) {
                    return ((JavaObjectself.dataGetStruct()).java_class();
                }
            });
            // Because we implement Java interfaces now, we need a new === that's
            // aware of those additional "virtual" supertypes
            if (!clazz.searchMethod("===").isUndefined()) {
                clazz.defineAlias("old_eqq""===");
                clazz.addMethod("==="new JavaMethodOne(clazz.) {
                    @Override
                    public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject arg) {
                        // TODO: WRONG - get interfaces from class
                        if (arg.respondsTo("java_object")) {
                            IRubyObject interfaces = self.getMetaClass().getInstanceVariables().getInstanceVariable("@java_interfaces");
                            assert interfaces instanceof RubyArray : "interface list was not an array";
                            return context.runtime.newBoolean(((RubyArrayinterfaces).op_diff(
                                    ((JavaClass) ((JavaObjectarg.dataGetStruct()).java_class()).interfaces()).equals(RubyArray.newArray(context.runtime)));
                        } else {
                            return RuntimeHelpers.invoke(contextself"old_eqq"arg);
                        }
                    }
                });
            }
        }
        // Now we add an "implement" and "implement_all" methods to the class
        if (!clazz.isMethodBound("implement"false)) {
            RubyClass singleton = clazz.getSingletonClass();
            // implement is called to force this class to create stubs for all
            // methods in the given interface, so they'll show up in the list
            // of methods and be invocable without passing through method_missing
            singleton.addMethod("implement"new JavaMethodOne(clazz.) {
                @Override
                public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject arg) {
                    IRubyObject javaInterfaces = self.getInstanceVariables().getInstanceVariable("@java_interfaces");
                    if (javaInterfaces != null && ((RubyArrayjavaInterfaces).includes(contextarg)) {
                        return RuntimeHelpers.invoke(contextarg"implement"self);
                    }
                    return context.runtime.getNil();
                }
            });
            // implement all forces implementation of all interfaces we intend
            // for this class to implement
            singleton.addMethod("implement_all"new JavaMethodOne(clazz.) {
                @Override
                public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject arg) {
                    RubyArray javaInterfaces = (RubyArrayself.getInstanceVariables().getInstanceVariable("@java_interfaces");
                    for (int i = 0; i < javaInterfaces.size(); i++) {
                        RuntimeHelpers.invoke(context, JavaUtilities.get_interface_module(selfjavaInterfaces.eltInternal(i)), "implement"self);
                    }
                    return javaInterfaces;
                }
            });
        }
    }
    public static void addRealImplClassNew(RubyClass clazz) {
        clazz.setAllocator(new ObjectAllocator() {
            private Constructor proxyConstructor;
            public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
                // if we haven't been here before, reify the class
                Class reifiedClass = klazz.getReifiedClass();
                if ( == null || .getDeclaringClass() != reifiedClass) {
                    if (reifiedClass == null) {
                        reifiedClass = Java.generateRealClass(klazz);
                    }
                     = Java.getRealClassConstructor(runtimereifiedClass);
                }
                IRubyObject newObj = Java.constructProxy(runtimeklazz);
                return newObj;
            }
        });
    }
    private static IRubyObject jcreateProxy(IRubyObject self) {
        RubyClass current = self.getMetaClass();
        // construct the new interface impl and set it into the object
        IRubyObject newObject = Java.newInterfaceImpl(self, Java.getInterfacesFromRubyClass(current));
        return JavaUtilities.set_java_object(selfselfnewObject);
    }
    private static void appendFeaturesToModule(ThreadContext contextIRubyObject selfRubyModule module) {
        // assuming the user wants a collection of interfaces that can be
        // included together. make it so.
        Ruby runtime = context.runtime;
        // not allowed for existing Java interface modules
        if (module.getInstanceVariables().hasInstanceVariable("@java_class") &&
                module.getInstanceVariables().getInstanceVariable("@java_class").isTrue()) {
            throw runtime.newTypeError("can not add Java interface to existing Java interface");
        }
        
        // To turn a module into an "interface collection" we add a class instance
        // variable to hold the list of interfaces, and modify append_features
        // for this module to call append_features on each of those interfaces as
        // well
        synchronized (module) {
            if (!module.getInstanceVariables().hasInstanceVariable("@java_interface_mods")) {
                RubyArray javaInterfaceMods = RubyArray.newArray(runtimeself);
                module.getInstanceVariables().setInstanceVariable("@java_interface_mods"javaInterfaceMods);
                RubyClass singleton = module.getSingletonClass();
                singleton.addMethod("append_features"new JavaMethodOneBlock(singleton.) {
                    @Override
                    public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject argBlock block) {
                        if (!(arg instanceof RubyClass)) {
                            throw context.runtime.newTypeError("append_features called with non-class");
                        }
                        RubyClass target = (RubyClass)arg;
                        RubyArray javaInterfaceMods = (RubyArray)self.getInstanceVariables().getInstanceVariable("@java_interface_mods");
                        target.include(javaInterfaceMods.toJavaArray());
                        return RuntimeHelpers.invokeAs(contextclazz.getSuperClass(), selfnameargblock);
                    }
                });
            } else {
                // already set up append_features, just add the interface if we haven't already
                RubyArray javaInterfaceMods =(RubyArray)module.getInstanceVariables().getInstanceVariable("@java_interface_mods");
                if (!javaInterfaceMods.includes(contextself)) {
                    javaInterfaceMods.append(self);
                }
            }
        }
    }
    public static IRubyObject extended(ThreadContext contextIRubyObject selfIRubyObject object) {
        if (!(self instanceof RubyModule)) {
            throw context.runtime.newTypeError(selfcontext.runtime.getModule());
        }
        RubyClass singleton = object.getSingletonClass();
        singleton.include(new IRubyObject[] {self});
        return singleton;
    }
    @JRubyMethod(name = "[]", rest = true)
    public static IRubyObject op_aref(ThreadContext contextIRubyObject selfIRubyObject[] args) {
        return JavaProxy.op_aref(contextselfargs);
    }
    @JRubyMethod(rest = true)
    public static IRubyObject impl(ThreadContext contextIRubyObject selfIRubyObject[] argsfinal Block implBlock) {
        Ruby runtime = context.runtime;
        if (!implBlock.isGiven()) throw runtime.newArgumentError("block required to call #impl on a Java interface");
        final RubyArray methodNames = (args.length > 0) ? runtime.newArray(args) : null;
        RubyClass implClass = RubyClass.newClass(runtimeruntime.getObject());
        implClass.include(new IRubyObject[] {self});
        IRubyObject implObject = implClass.callMethod(context"new");
        implClass.addMethod("method_missing",
                new org.jruby.internal.runtime.methods.JavaMethod(implClass.) {
                    @Override
                    public IRubyObject call(ThreadContext contextIRubyObject selfRubyModule clazzString nameIRubyObject[] argsBlock block) {
                        Arity.checkArgumentCount(context.runtimenameargs.length, 1, -1);
                        if (methodNames == null || methodNames.include_p(contextargs[0]).isTrue()) {
                            return implBlock.call(contextargs);
                        } else {
                            return clazz.getSuperClass().callMethod(context"method_missing"argsblock);
                        }
                    }
                });
        return implObject;
    }
    @JRubyMethod(name = "new", rest = true)
    public static IRubyObject rbNew(ThreadContext contextIRubyObject selfIRubyObject[] argsBlock block) {
        Ruby runtime = context.runtime;
        RubyClass implClass = (RubyClass)self.getInstanceVariables().getInstanceVariable("@__implementation");
        if (implClass == null) {
            implClass = RubyClass.newClass(runtime, (RubyClass)runtime.getClass("InterfaceJavaProxy"));
            implClass.include(new IRubyObject[] {self});
            RuntimeHelpers.setInstanceVariable(implClassself"@__implementation");
        }
        return RuntimeHelpers.invoke(contextimplClass"new"argsblock);
    }
New to GrepCode? Check out our FAQ X