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) 2001 Chad Fowler <chadfowler@chadfowler.com> Copyright (C) 2001 Alan Moore <alan_moore@gmx.net> Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2004 Thomas E Enebo <enebo@acm.org> Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net> Copyright (C) 2005 Charles O Nutter <headius@headius.com> Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org> 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 org.jruby.Ruby;
 
 
 @JRubyClass(name="Java::JavaMethod")
 public class JavaMethod extends JavaCallable {
 
     private static final Logger LOG = LoggerFactory.getLogger("JavaMethod");
 
     private final static boolean USE_HANDLES = .;
     private final static boolean HANDLE_DEBUG = false;
     private final Method method;
     private final Class boxedReturnType;
     private final boolean isFinal;
     private final JavaUtil.JavaConverter returnConverter;
 
     public Object getValue() {
         return ;
     }
 
     public static RubyClass createJavaMethodClass(Ruby runtimeRubyModule javaModule) {
         // TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
         // this type and it can't be marshalled. Confirm. JRUBY-415
         RubyClass result = 
             javaModule.defineClassUnder("JavaMethod"runtime.getObject(), .);
 
         JavaAccessibleObject.registerRubyMethods(runtimeresult);
         JavaCallable.registerRubyMethods(runtimeresult);
         
         result.defineAnnotatedMethods(JavaMethod.class);
 
         return result;
     }
 
     public JavaMethod(Ruby runtimeMethod method) {
         super(runtimeruntime.getJavaSupport().getJavaMethodClass(), method.getParameterTypes());
         this. = method;
         this. = Modifier.isFinal(method.getModifiers());
         if (method.getReturnType().isPrimitive() && method.getReturnType() != void.class) {
             this. = CodegenUtils.getBoxType(method.getReturnType());
        } else {
            this. = method.getReturnType();
        }
        boolean methodIsPublic = Modifier.isPublic(method.getModifiers());
        boolean classIsPublic = Modifier.isPublic(method.getDeclaringClass().getModifiers());
        // Special classes like Collections.EMPTY_LIST are inner classes that are private but 
        // implement public interfaces.  Their methods are all public methods for the public 
        // interface.  Let these public methods execute via setAccessible(true).
        if (.) {
            // we should be able to setAccessible ok...
            try {
                if (methodIsPublic &&
                    !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
                    accessibleObject().setAccessible(true);
                }
            } catch (SecurityException se) {
                // we shouldn't get here if JavaClass.CAN_SET_ACCESSIBLE is doing
                // what it should, so we warn.
               runtime.getWarnings().warn("failed to setAccessible: " + accessibleObject() + ", exception follows: " + se.getMessage());
            }
        }
        
         = JavaUtil.getJavaConverter(method.getReturnType());
    }
    public static JavaMethod create(Ruby runtimeMethod method) {
        return new JavaMethod(runtimemethod);
    }
    public static JavaMethod create(Ruby runtimeClass<?> javaClassString methodNameClass<?>[] argumentTypes) {
        try {
            Method method = javaClass.getMethod(methodNameargumentTypes);
            return create(runtimemethod);
        } catch (NoSuchMethodException e) {
            throw runtime.newNameError("undefined method '" + methodName + "' for class '" + javaClass.getName() + "'",
                    methodName);
        }
    }
    public static JavaMethod createDeclared(Ruby runtimeClass<?> javaClassString methodNameClass<?>[] argumentTypes) {
        try {
            return create(runtimejavaClass.getDeclaredMethod(methodNameargumentTypes));
        } catch (NoSuchMethodException e) {
            throw runtime.newNameError("undefined method '" + methodName + "' for class '" + javaClass.getName() + "'",
                    methodName);
        }
    }
    public static JavaMethod getMatchingDeclaredMethod(Ruby runtimeClass<?> javaClassString methodNameClass<?>[] argumentTypes) {
        // FIXME: do we really want 'declared' methods?  includes private/protected, and does _not_
        // include superclass methods.  also, the getDeclared calls may throw SecurityException if
        // we're running under a restrictive security policy.
        try {
            return create(runtimejavaClass.getDeclaredMethod(methodNameargumentTypes));
        } catch (NoSuchMethodException e) {
            // search through all declared methods to find a closest match
            MethodSearch: for (Method method : javaClass.getDeclaredMethods()) {
                if (method.getName().equals(methodName)) {
                    Class<?>[] targetTypes = method.getParameterTypes();
                
                    // for zero args case we can stop searching
                    if (targetTypes.length == 0 && argumentTypes.length == 0) {
                        return create(runtimemethod);
                    }
                    
                    TypeScan: for (int i = 0; i < argumentTypes.lengthi++) {
                        if (i >= targetTypes.lengthcontinue MethodSearch;
                        if (targetTypes[i].isAssignableFrom(argumentTypes[i])) {
                            continue TypeScan;
                        } else {
                            continue MethodSearch;
                        }
                    }
                    // if we get here, we found a matching method, use it
                    // TODO: choose narrowest method by continuing to search
                    return create(runtimemethod);
                }
            }
        }
        // no matching method found
        return null;
    }
    
    @Override
    public boolean equals(Object other) {
        return other instanceof JavaMethod &&
            this. == ((JavaMethod)other).;
    }
    
    @Override
    public int hashCode() {
        return .hashCode();
    }
    @Override
    public RubyString name() {
        return getRuntime().newString(.getName());
    }
    public int getArity() {
        return .;
    }
    @JRubyMethod(name = "public?")
    @Override
    public RubyBoolean public_p() {
        return getRuntime().newBoolean(Modifier.isPublic(.getModifiers()));
    }
    @JRubyMethod(name = "final?")
    public RubyBoolean final_p() {
        return getRuntime().newBoolean(Modifier.isFinal(.getModifiers()));
    }
    @JRubyMethod(rest = true)
    public IRubyObject invoke(IRubyObject[] args) {
        checkArity(args.length - 1);
        Object[] arguments = new Object[args.length - 1];
        convertArguments(argsarguments, 1);
        IRubyObject invokee = args[0];
        if(invokee.isNil()) {
            return invokeWithExceptionHandling(nullarguments);
        }
        Object javaInvokee = null;
        if (!isStatic()) {
            javaInvokee = JavaUtil.unwrapJavaValue(getRuntime(), invokee"invokee not a java object");
            if (! .getDeclaringClass().isInstance(javaInvokee)) {
                throw getRuntime().newTypeError("invokee not instance of method's class (" +
                                                  "got" + javaInvokee.getClass().getName() + " wanted " +
                                                  .getDeclaringClass().getName() + ")");
            }
            //
            // this test really means, that this is a ruby-defined subclass of a java class
            //
            if (javaInvokee instanceof InternalJavaProxy &&
                    // don't bother to check if final method, it won't
                    // be there (not generated, can't be!)
                    !Modifier.isFinal(.getModifiers())) {
                JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee)
                        .___getProxyClass();
                JavaProxyMethod jpm;
                if ((jpm = jpc.getMethod(.getName(), )) != null &&
                        jpm.hasSuperImplementation()) {
                    return invokeWithExceptionHandling(jpm.getSuperMethod(), javaInvokeearguments);
                }
            }
        }
        return invokeWithExceptionHandling(javaInvokeearguments);
    }
    @JRubyMethod(rest = true)
    public IRubyObject invoke_static(IRubyObject[] args) {
        checkArity(args.length);
        Object[] arguments = new Object[args.length];
        System.arraycopy(args, 0, arguments, 0, arguments.length);
        convertArguments(argsarguments, 0);
        return invokeWithExceptionHandling(nullarguments);
    }
    public IRubyObject return_type() {
        Class<?> klass = .getReturnType();
        
        if (klass.equals(void.class)) {
            return getRuntime().getNil();
        }
        return JavaClass.get(getRuntime(), klass);
    }
    public IRubyObject type_parameters() {
        return Java.getInstance(getRuntime(), .getTypeParameters());
    }
    public IRubyObject invokeDirect(Object javaInvokeeObject[] args) {
        checkArity(args.length);
        checkInstanceof(javaInvokee);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokeeargs);
        }
        return invokeDirectWithExceptionHandling(javaInvokeeargs);
    }
    public IRubyObject invokeDirect(Object javaInvokee) {
        assert .getDeclaringClass().isInstance(javaInvokee);
        checkArity(0);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokee);
        }
        return invokeDirectWithExceptionHandling(javaInvokee);
    }
    public IRubyObject invokeDirect(Object javaInvokeeObject arg0) {
        assert .getDeclaringClass().isInstance(javaInvokee);
        checkArity(1);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokeearg0);
        }
        return invokeDirectWithExceptionHandling(javaInvokeearg0);
    }
    public IRubyObject invokeDirect(Object javaInvokeeObject arg0Object arg1) {
        assert .getDeclaringClass().isInstance(javaInvokee);
        checkArity(2);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokeearg0arg1);
        }
        return invokeDirectWithExceptionHandling(javaInvokeearg0arg1);
    }
    public IRubyObject invokeDirect(Object javaInvokeeObject arg0Object arg1Object arg2) {
        assert .getDeclaringClass().isInstance(javaInvokee);
        checkArity(3);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokeearg0arg1arg2);
        }
        return invokeDirectWithExceptionHandling(javaInvokeearg0arg1arg2);
    }
    public IRubyObject invokeDirect(Object javaInvokeeObject arg0Object arg1Object arg2Object arg3) {
        assert .getDeclaringClass().isInstance(javaInvokee);
        checkArity(4);
        if (mightBeProxy(javaInvokee)) {
            return tryProxyInvocation(javaInvokeearg0arg1arg2arg3);
        }
        return invokeDirectWithExceptionHandling(javaInvokeearg0arg1arg2arg3);
    }
    public IRubyObject invokeStaticDirect(Object[] args) {
        checkArity(args.length);
        return invokeDirectWithExceptionHandling(nullargs);
    }
    public IRubyObject invokeStaticDirect() {
        checkArity(0);
        return invokeDirectWithExceptionHandling(null);
    }
    public IRubyObject invokeStaticDirect(Object arg0) {
        checkArity(1);
        return invokeDirectWithExceptionHandling(nullarg0);
    }
    public IRubyObject invokeStaticDirect(Object arg0Object arg1) {
        checkArity(2);
        return invokeDirectWithExceptionHandling(nullarg0arg1);
    }
    public IRubyObject invokeStaticDirect(Object arg0Object arg1Object arg2) {
        checkArity(3);
        return invokeDirectWithExceptionHandling(nullarg0arg1arg2);
    }
    public IRubyObject invokeStaticDirect(Object arg0Object arg1Object arg2Object arg3) {
        checkArity(4);
        return invokeDirectWithExceptionHandling(nullarg0arg1arg2arg3);
    }
    private void checkInstanceof(Object javaInvokeethrows RaiseException {
        if (!.getDeclaringClass().isInstance(javaInvokee)) {
            throw getRuntime().newTypeError("invokee not instance of method's class (" + "got" + javaInvokee.getClass().getName() + " wanted " + .getDeclaringClass().getName() + ")");
        }
    }
    private IRubyObject invokeWithExceptionHandling(Method methodObject javaInvokeeObject[] arguments) {
        try {
            Object result = method.invoke(javaInvokeearguments);
            return .convert(getRuntime(), result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearguments);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectSuperWithExceptionHandling(Method methodObject javaInvokeeObject... arguments) {
        // super calls from proxies must use reflected method
        // FIXME: possible to make handles do the superclass call?
        try {
            Object result = method.invoke(javaInvokeearguments);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearguments);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokeeObject[] arguments) {
        try {
            Object result = method.invoke(javaInvokeearguments);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearguments);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokee) {
        try {
            Object result = method.invoke(javaInvokee);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiae);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokeeObject arg0) {
        try {
            Object result = method.invoke(javaInvokeearg0);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearg0);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokeeObject arg0Object arg1) {
        try {
            Object result = method.invoke(javaInvokeearg0arg1);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearg0arg1);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokeeObject arg0Object arg1Object arg2) {
        try {
            Object result = method.invoke(javaInvokeearg0arg1arg2);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearg0arg1arg2);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject invokeDirectWithExceptionHandling(Method methodObject javaInvokeeObject arg0Object arg1Object arg2Object arg3) {
        try {
            Object result = method.invoke(javaInvokeearg0arg1arg2arg3);
            return convertReturn(result);
        } catch (IllegalArgumentException iae) {
            return handlelIllegalArgumentEx(methodiaearg0arg1arg2arg3);
        } catch (IllegalAccessException iae) {
            return handleIllegalAccessEx(methodiae);
        } catch (InvocationTargetException ite) {
            return handleInvocationTargetEx(itemethod);
        } catch (Throwable t) {
            return handleThrowable(tmethod);
        }
    }
    private IRubyObject convertReturn(Object result) {
        if (result != null && result.getClass() != ) {
            // actual type does not exactly match method return type, re-get converter
            // FIXME: when the only autoconversions are primitives, this won't be needed
            return JavaUtil.convertJavaToUsableRubyObject(getRuntime(), result);
        }
        return JavaUtil.convertJavaToUsableRubyObjectWithConverter(getRuntime(), result);
    }
        throw getRuntime().newTypeError("illegal access on '" + method.getName() + "': " + iae.getMessage());
    }
    private IRubyObject handlelIllegalArgumentEx(Method methodIllegalArgumentException iaeObject... argumentsthrows RaiseException {
        throw getRuntime().newTypeError(
                "for method " +
                method.getDeclaringClass().getSimpleName() +
                "." +
                method.getName() +
                " expected " +
                argument_types().inspect() +
                "; got: " +
                dumpArgTypes(arguments) +
                "; error: " +
                iae.getMessage());
    }
    private void convertArguments(IRubyObject[] argsInObject[] argsOutint from) {
        Class<?>[] types = ;
        for (int i = argsOut.length; --i >= 0; ) {
            argsOut[i] = argsIn[i+from].toJava(types[i]);
        }
    }
    public Class<?>[] getParameterTypes() {
        return ;
    }
    public Class<?>[] getExceptionTypes() {
        return .getExceptionTypes();
    }
    public Type[] getGenericParameterTypes() {
        return .getGenericParameterTypes();
    }
    public Type[] getGenericExceptionTypes() {
        return .getGenericExceptionTypes();
    }
    
    public Annotation[][] getParameterAnnotations() {
        return .getParameterAnnotations();
    }
    public boolean isVarArgs() {
        return .isVarArgs();
    }
    protected String nameOnInspection() {
        return "#<" + getType().toString() + "/" + .getName() + "(";
    }
    @JRubyMethod(name = "static?")
    public RubyBoolean static_p() {
        return getRuntime().newBoolean(isStatic());
    }
    
    public RubyBoolean bridge_p() {
        return getRuntime().newBoolean(.isBridge());
    }
    private boolean isStatic() {
        return Modifier.isStatic(.getModifiers());
    }
    public int getModifiers() {
        return .getModifiers();
    }
    public String toGenericString() {
        return .toGenericString();
    }
        return ;
    }
    private boolean mightBeProxy(Object javaInvokee) {
        // this test really means, that this is a ruby-defined subclass of a java class
        return javaInvokee instanceof InternalJavaProxy && !;
    }
    private IRubyObject tryProxyInvocation(Object javaInvokeeObject... args) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokeeargs);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokeeargs);
        }
    }
    private IRubyObject tryProxyInvocation(Object javaInvokee) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokee);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokee);
        }
    }
    private IRubyObject tryProxyInvocation(Object javaInvokeeObject arg0) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokeearg0);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokeearg0);
        }
    }
    private IRubyObject tryProxyInvocation(Object javaInvokeeObject arg0Object arg1) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokeearg0arg1);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokeearg0arg1);
        }
    }
    private IRubyObject tryProxyInvocation(Object javaInvokeeObject arg0Object arg1Object arg2) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokeearg0arg1arg2);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokeearg0arg1arg2);
        }
    }
    private IRubyObject tryProxyInvocation(Object javaInvokeeObject arg0Object arg1Object arg2Object arg3) {
        JavaProxyClass jpc = ((InternalJavaProxyjavaInvokee).___getProxyClass();
        JavaProxyMethod jpm;
        if ((jpm = jpc.getMethod(.getName(), )) != null && jpm.hasSuperImplementation()) {
            return invokeDirectSuperWithExceptionHandling(jpm.getSuperMethod(), javaInvokeearg0arg1arg2arg3);
        } else {
            return invokeDirectWithExceptionHandling(javaInvokeearg0arg1arg2arg3);
        }
    }
    public static RaiseException newMethodNotFoundError(Ruby runtimeClass targetString prettyNameString simpleName) {
        return runtime.newNameError("java method not found: " + target.getName() + "." + prettyNamesimpleName);
    }
    public static RaiseException newArgSizeMismatchError(Ruby runtimeClass ... argTypes) {
        return runtime.newArgumentError("argument count mismatch for method signature " + CodegenUtils.prettyParams(argTypes));
    }