Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.java.proxies;
  
 import java.util.Map;
 
 import org.jruby.Ruby;
 
 public class JavaProxy extends RubyObject {
     private static final boolean DEBUG = false;
 
     private JavaObject javaObject;
     Object object;
 
     public JavaProxy(Ruby runtimeRubyClass klazz) {
         super(runtimeklazz);
     }
 
     public JavaProxy(Ruby runtimeRubyClass klazzObject object) {
         super(runtimeklazz);
         this. = object;
     }
 
     private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
         public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
             return new JavaProxy(runtimeklazz);
         }
     };
 
     public static RubyClass createJavaProxy(ThreadContext context) {
         final Ruby runtime = context.runtime;
 
         RubyClass JavaProxy = runtime.defineClass("JavaProxy"runtime.getObject(), );
 
         JavaProxy.getSingletonClass().addReadWriteAttribute(context"java_class");
         JavaProxy.defineAnnotatedMethods(JavaProxy.class);
         JavaProxy.includeModule(runtime.getModule("JavaProxyMethods"));
 
         return JavaProxy;
     }
 
     @Override
     public Object dataGetStruct() {
         // for investigating and eliminating code that causes JavaObject to live
         if () Thread.dumpStack();
         return getJavaObject();
     }
 
     @Override
     public void dataWrapStruct(Object object) {
         this. = (JavaObjectobject;
         this. = .getValue();
     }
 
     public Object getObject() {
         // FIXME: Added this because marshal_spec seemed to reconstitute objects without calling dataWrapStruct
         // this resulted in object being null after unmarshalling...
         if ( == null) {
             if ( == null) {
                 throw getRuntime().newRuntimeError("Java wrapper with no contents: " + this.getMetaClass().getName());
            } else {
                 = .getValue();
            }
        }
        return ;
    }
    public void setObject(Object object) {
        this. = object;
    }
    public Object unwrap() { return getObject(); }
    private JavaObject getJavaObject() {
        if ( == null) {
             = JavaObject.wrap(getRuntime(), );
        }
        return ;
    }
    @Override
    public Class getJavaClass() {
        return getObject().getClass();
    }
    static JavaClass java_class(final ThreadContext contextfinal RubyModule module) {
        return (JavaClass) Helpers.invoke(contextmodule"java_class");
    }
    @JRubyMethod(meta = true, frame = true// framed for invokeSuper
    public static IRubyObject inherited(ThreadContext contextIRubyObject recvIRubyObject subclass) {
        IRubyObject subJavaClass = Helpers.invoke(contextsubclass"java_class");
        if (subJavaClass.isNil()) {
            subJavaClass = Helpers.invoke(contextrecv"java_class");
            Helpers.invoke(contextsubclass"java_class="subJavaClass);
        }
        return Helpers.invokeSuper(contextrecvsubclass.);
    }
    @JRubyMethod(meta = true)
    public static RubyClass singleton_class(final IRubyObject self) {
        return ((RubyClassself).getSingletonClass();
    }
    @JRubyMethod(name = "[]", meta = true, rest = true)
    public static IRubyObject op_aref(ThreadContext contextIRubyObject selfIRubyObject[] args) {
        final JavaClass javaClass = java_class(context, (RubyModuleself);
        if ( args.length > 0 ) { // construct new array proxy (ArrayJavaProxy)
            return new ArrayJavaProxyCreator(contextjavaClassargs); // e.g. Byte[64]
        }
        return Java.get_proxy_class(javaClass, Helpers.invoke(contextjavaClass"array_class"));
    }
    @JRubyMethod(meta = true)
    public static IRubyObject new_array(ThreadContext contextIRubyObject selfIRubyObject len) {
        final JavaClass javaClass = java_class(context, (RubyModuleself);
        final Class<?> componentType = javaClass.javaClass();
        final int length = (intlen.convertToInteger().getLongValue();
        return ArrayJavaProxy.newArray(context.runtimecomponentTypelength);
    }
    @JRubyMethod(name = "__persistent__=", meta = true)
    public static IRubyObject persistent(final IRubyObject clazzfinal IRubyObject value) {
        ((RubyClassclazz).getRealClass().setCacheProxyvalue.isTrue() );
        return value;
    }
    @JRubyMethod(name = "__persistent__", meta = true)
    public static IRubyObject persistent(final ThreadContext contextfinal IRubyObject clazz) {
        return context.runtime.newBoolean(((RubyClassclazz).getRealClass().getCacheProxy());
    }
    @Override
    public IRubyObject initialize_copy(IRubyObject original) {
        super.initialize_copy(original);
        // because we lazily init JavaObject in the data-wrapped slot, explicitly copy over the object
        setObject( ((JavaProxyoriginal).getObject() );
        return this;
    }

    
Create a name/newname map of fields to be exposed as methods.
    private static Map<StringStringgetFieldListFromArgs(final IRubyObject[] args) {
        final Map<StringStringmap = new HashMap<StringString>();
        // Get map of all fields we want to define.
        for (int i = 0; i < args.lengthi++) {
            final IRubyObject arg = args[i];
            if ( arg instanceof RubyHash ) {
                ((RubyHasharg).visitAll(new Visitor() {
                    @Override
                    public void visit(IRubyObject keyIRubyObject value) {
                        map.put(key.asString().toString(), value.asString().toString());
                    }
                });
            } else {
                String value = arg.asString().toString();
                map.put(valuevalue);
            }
        }
        return map;
    }
    // Look through all mappings to find a match entry for this field
    private static void installField(final ThreadContext context,
        final Map<StringStringfieldMapfinal Field field,
        final RubyModule moduleboolean asReaderboolean asWriter) {
        final String fieldName = field.getName();
        final Iterator<Map.Entry<String,String>> iter = fieldMap.entrySet().iterator();
        while ( iter.hasNext() ) {
            final Map.Entry<String,Stringentry = iter.next();
            if ( entry.getKey().equalsfieldName ) ) {
                if ( Ruby.isSecurityRestricted() && ! Modifier.isPublic(field.getModifiers()) ) {
                    throw context.runtime.newSecurityError("Cannot change accessibility on fields in a restricted mode: field '" + fieldName + "'");
                }
                String asName = entry.getValue();
                if ( Modifier.isStatic(field.getModifiers()) ) {
                    if ( asReader ) {
                        module.getSingletonClass().addMethod(asNamenew StaticFieldGetter(fieldNamemodulefield));
                    }
                    if ( asWriter ) {
                        if ( Modifier.isFinal(field.getModifiers()) ) {
                            throw context.runtime.newSecurityError("Cannot change final field '" + fieldName + "'");
                        }
                        module.getSingletonClass().addMethod(asName + '='new StaticFieldSetter(fieldNamemodulefield));
                    }
                } else {
                    if ( asReader ) {
                        module.addMethod(asNamenew InstanceFieldGetter(fieldNamemodulefield));
                    }
                    if ( asWriter ) {
                        if ( Modifier.isFinal(field.getModifiers()) ) {
                            throw context.runtime.newSecurityError("Cannot change final field '" + fieldName + "'");
                        }
                        module.addMethod(asName + '='new InstanceFieldSetter(fieldNamemodulefield));
                    }
                }
                iter.remove();
                break;
            }
        }
    }
    private static void findFields(final ThreadContext context,
        final RubyModule topModulefinal IRubyObject[] args,
        final boolean asReaderfinal boolean asWriter) {
        final Map<StringStringfieldMap = getFieldListFromArgs(args);
        for (RubyModule module = topModulemodule != nullmodule = module.getSuperClass()) {
            final Class<?> javaClass = JavaClass.getJavaClassIfProxy(contextmodule);
            // Hit a non-java proxy class (included Modules can be a cause of this...skip)
            if ( javaClass == null ) continue;
            Field[] fields = JavaClass.getDeclaredFields(javaClass);
            for (int j = 0; j < fields.lengthj++) {
                installField(contextfieldMapfields[j], moduleasReaderasWriter);
            }
        }
        // We could not find all of them print out first one (we could print them all?)
        if ( ! fieldMap.isEmpty() ) {
            throw JavaClass.undefinedFieldError(context.runtime,
                    topModule.getName(), fieldMap.keySet().iterator().next());
        }
    }
    @JRubyMethod(meta = true, rest = true)
    public static IRubyObject field_accessor(ThreadContext contextIRubyObject selfIRubyObject[] args) {
        findFields(context, (RubyModuleselfargstruetrue);
        return context.nil;
    }
    @JRubyMethod(meta = true, rest = true)
    public static IRubyObject field_reader(ThreadContext contextIRubyObject selfIRubyObject[] args) {
        findFields(context, (RubyModuleselfargstruefalse);
        return context.nil;
    }
    @JRubyMethod(meta = true, rest = true)
    public static IRubyObject field_writer(ThreadContext contextIRubyObject selfIRubyObject[] args) {
        findFields(context, (RubyModuleselfargsfalsetrue);
        return context.nil;
    }
    @Override
    @JRubyMethod(name = "equal?")
    public IRubyObject equal_p(ThreadContext contextIRubyObject other) {
        if ( other instanceof JavaProxy ) {
            boolean equal = getObject() == ((JavaProxyother).getObject();
            return context.runtime.newBoolean(equal);
        }
        return context.runtime.getFalse();
    }
    public IRubyObject java_send(ThreadContext contextIRubyObject rubyName) {
        String name = rubyName.asJavaString();
        Ruby runtime = context.runtime;
        JavaMethod method = new JavaMethod(runtimegetMethod(name));
        return method.invokeDirect(getObject());
    }
    public IRubyObject java_send(ThreadContext contextIRubyObject rubyNameIRubyObject argTypes) {
        String name = rubyName.asJavaString();
        RubyArray argTypesAry = argTypes.convertToArray();
        Ruby runtime = context.runtime;
        checkArgSizeMismatch(runtime, 0, argTypesAry);
        JavaMethod method = new JavaMethod(runtimegetMethod(name));
        return method.invokeDirect(getObject());
    }
    public IRubyObject java_send(ThreadContext contextIRubyObject rubyNameIRubyObject argTypesIRubyObject arg0) {
        String name = rubyName.asJavaString();
        RubyArray argTypesAry = argTypes.convertToArray();
        Ruby runtime = context.runtime;
        checkArgSizeMismatch(runtime, 1, argTypesAry);
        Class argTypeClass = (ClassargTypesAry.eltInternal(0).toJava(Class.class);
        JavaMethod method = new JavaMethod(runtimegetMethod(nameargTypeClass));
        return method.invokeDirect(getObject(), arg0.toJava(argTypeClass));
    }
    @JRubyMethod(required = 4, rest = true)
    public IRubyObject java_send(ThreadContext contextIRubyObject[] args) {
        Ruby runtime = context.runtime;
        String name = args[0].asJavaString();
        RubyArray argTypesAry = args[1].convertToArray();
        final int argsLen = args.length - 2;
        checkArgSizeMismatch(runtimeargsLenargTypesAry);
        Class[] argTypesClasses = (Class[]) argTypesAry.toArray(new Class[argsLen]);
        Object[] javaArgs = new Object[argsLen];
        for ( int i = 0; i < argsLeni++ ) {
            javaArgs[i] = args[i + 2].toJavaargTypesClasses[i] );
        }
        JavaMethod method = new JavaMethod(runtimegetMethod(nameargTypesClasses));
        return method.invokeDirect(getObject(), javaArgs);
    }
    private static void checkArgSizeMismatch(final Ruby runtimefinal int expectedfinal RubyArray argTypes) {
        if ( argTypes.size() != expected ) {
            Class[] argTypesClasses = (Class[]) argTypes.toArray(new Class[argTypes.size()]);
            throw JavaMethod.newArgSizeMismatchError(runtimeargTypesClasses);
        }
    }
    public IRubyObject java_method(ThreadContext contextIRubyObject rubyName) {
        String name = rubyName.asJavaString();
        return getRubyMethod(name);
    }
    public IRubyObject java_method(ThreadContext contextIRubyObject rubyNameIRubyObject argTypes) {
        String name = rubyName.asJavaString();
        RubyArray argTypesAry = argTypes.convertToArray();
        Class[] argTypesClasses = (Class[]) argTypesAry.toArray(new Class[argTypesAry.size()]);
        return getRubyMethod(nameargTypesClasses);
    }
    public IRubyObject marshal_dump() {
        if ( ! Serializable.class.isAssignableFrom(.getClass()) ) {
            throw getRuntime().newTypeError("Java type is not serializable, cannot be marshaled " + getJavaClass());
        }
        try {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            new ObjectOutputStream(bytes).writeObject();
            return getRuntime().newString(new ByteList(bytes.toByteArray(), false));
        }
        catch (IOException ex) {
            throw getRuntime().newTypeError("Java type is not serializable: " + ex.getMessage());
        }
    }
    public IRubyObject marshal_load(final ThreadContext contextfinal IRubyObject str) {
        try {
            ByteList byteList = str.convertToString().getByteList();
            ByteArrayInputStream bytes = new ByteArrayInputStream(byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
            this. = new JRubyObjectInputStream(context.runtimebytes).readObject();
            return this;
        }
        catch (IOException ex) {
            throw context.runtime.newIOErrorFromException(ex);
        }
        catch (ClassNotFoundException ex) {
            throw context.runtime.newTypeError("Class not found unmarshaling Java type: " + ex.getLocalizedMessage());
        }
    }

    
We override RubyBasicObject.inspectHashCode to be the identity hash of the contained object, so it remains consistent across wrappers.

Returns:
The identity hashcode of the wrapped object
    @Override
    protected int inspectHashCode() {
        return System.identityHashCode();
    }
    private Method getMethod(String nameClass... argTypes) {
        try {
            return getObject().getClass().getMethod(nameargTypes);
        } catch (NoSuchMethodException nsme) {
            throw JavaMethod.newMethodNotFoundError(getRuntime(), getObject().getClass(), name + CodegenUtils.prettyParams(argTypes), name);
        }
    }
    private MethodInvoker getMethodInvoker(Method method) {
        if (Modifier.isStatic(method.getModifiers())) {
            return new StaticMethodInvoker(.getMetaClass(), method);
        } else {
            return new InstanceMethodInvoker(method);
        }
    }
    private RubyMethod getRubyMethod(String nameClass... argTypes) {
        Method jmethod = getMethod(nameargTypes);
        if (Modifier.isStatic(jmethod.getModifiers())) {
            return RubyMethod.newMethod(.getSingletonClass(), CodegenUtils.prettyParams(argTypes).toString(), .getSingletonClass(), namegetMethodInvoker(jmethod), getMetaClass());
        } else {
            return RubyMethod.newMethod(, CodegenUtils.prettyParams(argTypes).toString(), namegetMethodInvoker(jmethod), this);
        }
    }
    @Override
    @SuppressWarnings("unchecked")
    public Object toJava(final Class type) {
        final Object object = getObject();
        final Class<?> clazz = object.getClass();
        if ( type.isAssignableFrom(clazz) ) return object;
        throw getRuntime().newTypeError("failed to coerce " + clazz.getName() + " to " + type.getName());
    }
    @Override
    public Object getVariable(int index) {
        return super.getVariable(index);
    }
    @Override
    public void setVariable(int indexObject value) {
        super.setVariable(indexvalue);
    }

    
rb_singleton_class Note: this method is specialized for RubyFixnum, RubySymbol, RubyNil and RubyBoolean Will either return the existing singleton class for this object, or create a new one and return that.
    @Override
    public RubyClass getSingletonClass() {
        return super.getSingletonClass();
    }
    private void confirmCachedProxy(String message) {
        final RubyClass realClass = .getRealClass();
        if ( ! realClass.getCacheProxy() ) {
            final Ruby runtime = getRuntime();
            if (.) {
                runtime.getWarnings().warnOnce(.., MessageFormat.format(messagerealClass));
            } else {
                runtime.getWarnings().warn(MessageFormat.format(messagerealClass));
                realClass.setCacheProxy(true);
                runtime.getJavaSupport().getObjectProxyCache().put(getObject(), this);
            }
        }
    }
    private static final String NONPERSISTENT_IVAR_MESSAGE = "instance vars on non-persistent Java type {0} (http://wiki.jruby.org/Persistence)";
    private static final String NONPERSISTENT_SINGLETON_MESSAGE = "singleton on non-persistent Java type {0} (http://wiki.jruby.org/Persistence)";
New to GrepCode? Check out our FAQ X