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;
     protected Object object;
     
     public JavaProxy(Ruby runtimeRubyClass klazz) {
         super(runtimeklazz);
     }
 
     public JavaProxy(Ruby runtimeRubyClass klazzObject object) {
         super(runtimeklazz);
         this. = object;
     }
 
     @Override
     public Object dataGetStruct() {
         // for investigating and eliminating code that causes JavaObject to live
         if () Thread.dumpStack();
         lazyJavaObject();
         return ;
     }
 
     @Override
     public void dataWrapStruct(Object object) {
         this. = (JavaObject)object;
         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;
     }
 
     private void lazyJavaObject() {
         if ( == null) {
              = JavaObject.wrap(getRuntime(), );
         }
     }
 
     @Override
     public Class getJavaClass() {
        return .getClass();
    }
    
    public static RubyClass createJavaProxy(ThreadContext context) {
        Ruby runtime = context.runtime;
        
        RubyClass javaProxy = runtime.defineClass("JavaProxy"runtime.getObject(), new ObjectAllocator() {
            public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
                return new JavaProxy(runtimeklazz);
            }
        });
        
        RubyClass singleton = javaProxy.getSingletonClass();
        
        singleton.addReadWriteAttribute(context"java_class");
        
        javaProxy.defineAnnotatedMethods(JavaProxy.class);
        javaProxy.includeModule(runtime.getModule("JavaProxyMethods"));
        
        return javaProxy;
    }
    // framed for invokeSuper
    @JRubyMethod(frame = true, meta = true)
    public static IRubyObject inherited(ThreadContext contextIRubyObject recvIRubyObject subclass) {
        IRubyObject subJavaClass = RuntimeHelpers.invoke(contextsubclass"java_class");
        if (subJavaClass.isNil()) {
            subJavaClass = RuntimeHelpers.invoke(contextrecv"java_class");
            RuntimeHelpers.invoke(contextsubclass"java_class="subJavaClass);
        }
        return RuntimeHelpers.invokeSuper(contextrecvsubclass.);
    }
    
    @JRubyMethod(meta = true)
    public static IRubyObject singleton_class(IRubyObject recv) {
        return ((RubyClass)recv).getSingletonClass();
    }
    
    @JRubyMethod(name = "[]", meta = true, rest = true)
    public static IRubyObject op_aref(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        IRubyObject javaClass = RuntimeHelpers.invoke(contextrecv"java_class");
        if (args.length > 0) {
            // construct new array proxy (ArrayJavaProxy)
            ArrayJavaProxyCreator ajpc = new ArrayJavaProxyCreator(context.runtime);
            ajpc.setup(contextjavaClassargs);
            return ajpc;
        } else {
            return Java.get_proxy_class(javaClass, RuntimeHelpers.invoke(contextjavaClass"array_class"));
        }
    }
    @JRubyMethod(name = "__persistent__=", meta = true)
    public static IRubyObject persistent(IRubyObject clsIRubyObject value) {
        ((RubyClass)cls).getRealClass().setCacheProxy(value.isTrue());
        return value;
    }
    @JRubyMethod(name = "__persistent__", meta = true)
    public static IRubyObject persistent(ThreadContext contextIRubyObject cls) {
        return context.runtime.newBoolean(((RubyClass)cls).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(((JavaProxy)original).);
        return this;
    }
    private static Class<?> getJavaClass(ThreadContext contextRubyModule module) {
        try {
        IRubyObject jClass = RuntimeHelpers.invoke(contextmodule"java_class");
        return !(jClass instanceof JavaClass) ? null : ((JavaClassjClass).javaClass();
        } catch (Exception e) { return null; }
    }
    
    
Create a name/newname map of fields to be exposed as methods.
    private static Map<StringStringgetFieldListFromArgs(IRubyObject[] args) {
        final Map<StringStringmap = new HashMap<StringString>();
        
        // Get map of all fields we want to define.  
        for (int i = 0; i < args.lengthi++) {
            if (args[iinstanceof RubyHash) {
                ((RubyHashargs[i]).visitAll(new Visitor() {
                    @Override
                    public void visit(IRubyObject keyIRubyObject value) {
                        map.put(key.asString().toString(), value.asString().toString());
                    }
                });
            } else {
                String value = args[i].asString().toString();
                map.put(valuevalue);
            }
        }
        
        return map;
    }
    // Look through all mappings to find a match entry for this field
    private static void installField(ThreadContext contextMap<StringStringfieldMap,
            Field fieldRubyModule moduleboolean asReaderboolean asWriter) {
        boolean isFinal = Modifier.isFinal(field.getModifiers());
        for (Iterator<Map.Entry<String,String>> iter = fieldMap.entrySet().iterator(); iter.hasNext();) {
            Map.Entry<String,Stringentry = iter.next();
            String key = entry.getKey();
            if (key.equals(field.getName())) {
                if (Ruby.isSecurityRestricted() && !Modifier.isPublic(field.getModifiers())) {
                    throw context.runtime.newSecurityError("Cannot change accessibility on fields in a restricted mode: field '" + field.getName() + "'");
                }
                
                String asName = entry.getValue();
                if (Modifier.isStatic(field.getModifiers())) {
                    if (asReadermodule.getSingletonClass().addMethod(asNamenew StaticFieldGetter(keymodulefield));
                    if (asWriter) {
                        if (isFinal) {
                            throw context.runtime.newSecurityError("Cannot change final field '" + field.getName() + "'");
                        }
                        module.getSingletonClass().addMethod(asName + "="new StaticFieldSetter(keymodulefield));
                    }
                } else {
                    if (asReadermodule.addMethod(asNamenew InstanceFieldGetter(keymodulefield));
                    if (asWriter) {
                        if (isFinal) {
                            throw context.runtime.newSecurityError("Cannot change final field '" + field.getName() + "'");
                        }
                        module.addMethod(asName + "="new InstanceFieldSetter(keymodulefield));
                    }
                }
                
                iter.remove();
                break;
            }
        }
    }    
    private static void findFields(ThreadContext contextRubyModule topModule,
            IRubyObject args[], boolean asReaderboolean asWriter) {
        Map<StringStringfieldMap = getFieldListFromArgs(args);
        
        for (RubyModule module = topModulemodule != nullmodule = module.getSuperClass()) {
            Class<?> javaClass = getJavaClass(contextmodule);
            
            // Hit a non-java proxy class (included Modules can be a cause of this...skip)
            if (javaClass == nullcontinue;
            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 recvIRubyObject[] args) {
        findFields(context, (RubyModulerecvargstruetrue);
        return context.runtime.getNil();
    }
    @JRubyMethod(meta = true, rest = true)
    public static IRubyObject field_reader(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        findFields(context, (RubyModulerecvargstruefalse);
        return context.runtime.getNil();
    }
    
    @JRubyMethod(meta = true, rest = true)
    public static IRubyObject field_writer(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        findFields(context, (RubyModulerecvargsfalsetrue);
        return context.runtime.getNil();
    }
    @JRubyMethod(name = "equal?")
    public IRubyObject equal_p(ThreadContext contextIRubyObject other) {
        Ruby runtime = context.runtime;
        if (other instanceof JavaProxy) {
            boolean equal = getObject() == ((JavaProxy)other).getObject();
            return runtime.newBoolean(equal);
        }
        return 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;
        if (argTypesAry.size() != 0) {
            Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argTypesAry.size()]);
            throw JavaMethod.newArgSizeMismatchError(runtimeargTypesClasses);
        }
        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;
        if (argTypesAry.size() != 1) {
            Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argTypesAry.size()]);
            throw JavaMethod.newArgSizeMismatchError(runtimeargTypesClasses);
        }
        Class argTypeClass = (Class)argTypesAry.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();
        int argsLen = args.length - 2;
        if (argTypesAry.size() != argsLen) {
            Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argTypesAry.size()]);
            throw JavaMethod.newArgSizeMismatchError(runtimeargTypesClasses);
        }
        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(runtimegetMethod(nameargTypesClasses));
        return method.invokeDirect(getObject(), argsAry);
    }
    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())) {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject();
                return getRuntime().newString(new ByteList(baos.toByteArray()));
            } catch (IOException ioe) {
                throw getRuntime().newTypeError("Java type is not serializable: " + ioe.getMessage());
            }
        } else {
            throw getRuntime().newTypeError("Java type is not serializable, cannot be marshaled " + getJavaClass());
        }
    }
    public IRubyObject marshal_load(ThreadContext contextIRubyObject str) {
        try {
            ByteList byteList = str.convertToString().getByteList();
            ByteArrayInputStream bais = new ByteArrayInputStream(byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
            ObjectInputStream ois = new JRubyObjectInputStream(context.runtimebais);
             = ois.readObject();
            return this;
        } catch (IOException ioe) {
            throw context.runtime.newIOErrorFromException(ioe);
        } catch (ClassNotFoundException cnfe) {
            throw context.runtime.newTypeError("Class not found unmarshaling Java type: " + cnfe.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), .getSingletonClass(), namegetMethodInvoker(jmethod), getMetaClass());
        } else {
            return RubyMethod.newMethod(, CodegenUtils.prettyParams(argTypes), namegetMethodInvoker(jmethod), this);
        }
    }
    @Override
    public Object toJava(Class type) {
        Object obj = getObject();
        if (type.isAssignableFrom(obj.getClass())) {
            return obj;
        } else {
            return super.toJava(type);
        }
    }
    @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) {
        RubyClass realClass = .getRealClass();
        if (!realClass.getCacheProxy()) {
            if (.) {
                getRuntime().getWarnings().warnOnce(.., MessageFormat.format(messagerealClass));
            } else {
                getRuntime().getWarnings().warn(MessageFormat.format(messagerealClass));
                realClass.setCacheProxy(true);
                getRuntime().getJavaSupport().getObjectProxyCache().put(getObject(), this);
            }
        }
    }
    
    public Object unwrap() {
        return getObject();
    }
    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