Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.java.invokers;
  
  
 import org.jruby.Ruby;
 import static org.jruby.java.dispatch.CallableSelector.newCallableCache;
 import static org.jruby.util.CodegenUtils.prettyParams;
 
 public abstract class RubyToJavaInvoker extends JavaMethod {
 
     static final IntHashMap<JavaCallableNULL_CACHE = IntHashMap.nullMap();
 
     protected final JavaCallable javaCallable/* null if multiple callable members */
     protected final JavaCallable[][] javaCallables/* != null if javaCallable == null */
     protected final JavaCallable[] javaVarargsCallables/* != null if any var args callables */
     protected final int minVarargsArity;
 
     // in case multiple callables (overloaded Java method - same name different args)
     // for the invoker exists  CallableSelector caches resolution based on args here
     final IntHashMap<JavaCallablecache;
 
     private final Ruby runtime;
     private final Member[] members;
 
     RubyToJavaInvoker(RubyModule hostMember[] members) {
         super(host..);
         this. = members;
         this. = host.getRuntime();
         // we set all Java methods to optional, since many/most have overloads
         setArity(.);
 
         // initialize all the callables for this method
         final JavaCallable callable;
         final JavaCallable[][] callables;
         JavaCallable[] varargsCallables = null;
         int varArgsArity = .;
 
         final int length = members.length;
         if ( length == 1 ) {
             callable = createCallable(members[0]);
             if ( callable.isVarArgs() ) {
                 varargsCallables = createCallableArray(callable);
             }
             callables = null;
 
              = // if there's a single callable - matching (and thus the cache) won't be used
         }
         else {
             callable = null;
 
             IntHashMap<ArrayList<JavaCallable>> arityMap = new IntHashMap<ArrayList<JavaCallable>>(length, 1);
 
             ArrayList<JavaCallablevarArgs = nullint maxArity = 0;
             for ( int i = 0; i < lengthi++ ) {
                 final Member method = members[i];
                 final int currentArity = getMemberParameterTypes(method).length;
                 maxArity = Math.max(currentAritymaxArity);
 
                 ArrayList<JavaCallablemethodsForArity = arityMap.get(currentArity);
                 if (methodsForArity == null) {
                     // most calls have 2-3 callables length (a.k.a. overrides)
                     // using capacity of length is a win-win here - will (likely)
                     // use small internal [len] + no resizing even in worst case
                     methodsForArity = new ArrayList<JavaCallable>(length);
                     arityMap.put(currentAritymethodsForArity);
                 }
 
                 final JavaCallable javaMethod = createCallable(method);
                 methodsForArity.add(javaMethod);
 
                 if ( isMemberVarArgs(method) ) {
                     varArgsArity = Math.min(currentArity - 1, varArgsArity);
                     if (varArgs == nullvarArgs = new ArrayList<JavaCallable>(length);
                     varArgs.add(javaMethod);
                 }
             }
 
             callables = createCallableArrayArray(maxArity + 1);
             for (IntHashMap.Entry<ArrayList<JavaCallable>> entry : arityMap.entrySet()) {
                ArrayList<JavaCallablemethodsForArity = entry.getValue();
                JavaCallable[] methodsArray = methodsForArity.toArray(createCallableArray(methodsForArity.size()));
                callablesentry.getKey() /* int */ ] = methodsArray;
            }
            if (varArgs != null /* && varargsMethods.size() > 0 */) {
                varargsCallables = varArgs.toArraycreateCallableArray(varArgs.size()) );
            }
             = newCallableCache();
        }
        this. = callable;
        this. = callables;
        this. = varargsCallables;
        this. = varArgsArity;
        // if it's not overloaded, set up a NativeCall
        if ( != null) {
            // no constructor support yet
            if ( instanceof org.jruby.javasupport.JavaMethod) {
                setNativeCallIfPublic( ((org.jruby.javasupport.JavaMethod).getValue() );
            }
        } else { // use the lowest-arity non-overload
            for ( int i = 0; i.i++ ) {
                final JavaCallable[] callablesForArity = [i];
                if ( callablesForArity == null || callablesForArity.length != 1 ) continue;
                if ( callablesForArity[0] instanceof org.jruby.javasupport.JavaMethod ) {
                    final Method method = ((org.jruby.javasupport.JavaMethodcallablesForArity[0]).getValue();
                    if ( setNativeCallIfPublicmethod ) ) break;
                }
            }
        }
    }
    private boolean setNativeCallIfPublic(final Method method) {
        final int mod = method.getModifiers(); // only public, since non-public don't bind
        if ( Modifier.isPublic(mod) && Modifier.isPublicmethod.getDeclaringClass().getModifiers() ) ) {
            setNativeCall(method.getDeclaringClass(), method.getName(), method.getReturnType(), method.getParameterTypes(), Modifier.isStatic(mod), true);
            return true;
        }
        return false;
    }
    protected final Member[] getMembers() {
        return ;
    }
    protected AccessibleObject[] getAccessibleObjects() {
        return (AccessibleObject[]) getMembers();
    }
    protected abstract JavaCallable createCallable(Ruby runtimeMember member);
    protected abstract JavaCallable[] createCallableArray(JavaCallable callable);
    protected abstract JavaCallable[] createCallableArray(int size);
    protected abstract JavaCallable[][] createCallableArrayArray(int size);
    protected abstract Class[] getMemberParameterTypes(Member member);
    protected abstract boolean isMemberVarArgs(Member member);
    //final int getMemberArity(Member member) {
    //    return getMemberParameterTypes(member).length;
    //}
    public static Object[] convertArguments(final ParameterTypes methodfinal IRubyObject[] args) {
        final Class<?>[] paramTypes = method.getParameterTypes();
        final Object[] javaArgsfinal int len = args.length;
        if ( method.isVarArgs() ) {
            final int last = paramTypes.length - 1;
            javaArgs = new Objectlast + 1 ];
            for ( int i = 0; i < lasti++ ) {
                javaArgs[i] = args[i].toJava(paramTypes[i]);
            }
            javaArgslast ] = convertVarArgumentsOnly(paramTypeslast ], lastargs);
        }
        else {
            javaArgs = new Object[len];
            for ( int i = 0; i < leni++ ) {
                javaArgs[i] = args[i].toJava(paramTypes[i]);
            }
        }
        return javaArgs;
    }
    private static Object convertVarArgumentsOnly(final Class<?> varArrayType,
        final int varStartfinal IRubyObject[] args) {
        final int varCount = args.length - varStart;
        if ( args.length == 0 || varCount <= 0 ) {
            return Array.newInstance(varArrayType.getComponentType(), 0);
        }
        if ( varCount == 1 && args[varStartinstanceof ArrayJavaProxy ) {
            // we may have a pre-created array to pass; try that first
            return args[varStart].toJava(varArrayType);
        }
        final Class<?> compType = varArrayType.getComponentType();
        final Object varArgs = Array.newInstance(compTypevarCount);
        for ( int i = 0; i < varCounti++ ) {
            Array.set(varArgsiargs[varStart + i].toJava(compType));
        }
        return varArgs;
    }
    static JavaProxy castJavaProxy(final IRubyObject self) {
        assert self instanceof JavaProxy : "Java methods can only be invoked on Java objects";
        return (JavaProxyself;
    }
    static void trySetAccessible(AccessibleObject... accesibles) {
        if ( ! Ruby.isSecurityRestricted() ) {
            try { AccessibleObject.setAccessible(accesiblestrue); }
            catch(SecurityException e) {}
        }
    }
    protected JavaCallable findCallable(IRubyObject selfString nameIRubyObject[] argsfinal int arity) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            final JavaCallable[] callablesForArity;
            if ( arity >= . || (callablesForArity = [arity]) == null ) {
                if ( ( callable = matchVarArgsCallableArityN(selfargs) ) == null ) {
                    throw .newArgumentError(args.length. - 1);
                }
                return callable;
            }
            callable = CallableSelector.matchingCallableArityN(callablesForArityargs);
            if ( callable == null ) {
                if ( ( callable = matchVarArgsCallableArityN(selfargs) ) == null ) {
                    throw newErrorDueArgumentTypeMismatch(selfcallablesForArityargs);
                }
            }
        }
        else {
            if ( ! callable.isVarArgs() ) checkCallableArity(callableargs.length);
        }
        return callable;
    }
        final JavaCallable[] varArgsCallables = this.;
        if ( varArgsCallables != null ) {
            JavaCallable callable = CallableSelector.matchingCallableArityN(varArgsCallablesargs);
            if ( callable == null ) {
                throw newErrorDueArgumentTypeMismatch(selfvarArgsCallablesargs);
            }
            return callable;
        }
        return null;
    }
    protected final JavaCallable findCallableArityZero(IRubyObject selfString name) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            // TODO: varargs?
            final JavaCallable[] callablesForArity;
            if ( . == 0 || (callablesForArity = [0]) == null ) {
                throw newErrorDueNoMatchingCallable(selfname);
            }
            callable = callablesForArity[0];
        }
        else {
            checkCallableArity(callable, 0);
        }
        return callable;
    }
    protected final JavaCallable findCallableArityOne(IRubyObject selfString nameIRubyObject arg0) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            // TODO: varargs?
            final JavaCallable[] callablesForArity;
            if ( . <= 1 || (callablesForArity = [1]) == null ) {
                throw .newArgumentError(1, . - 1);
            }
            callable = CallableSelector.matchingCallableArityOne(callablesForArityarg0);
            if ( callable == null ) {
                throw newErrorDueArgumentTypeMismatch(selfcallablesForArityarg0);
            }
        }
        else {
            checkCallableArity(callable, 1);
        }
        return callable;
    }
    protected final JavaCallable findCallableArityTwo(IRubyObject selfString nameIRubyObject arg0IRubyObject arg1) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            // TODO: varargs?
            final JavaCallable[] callablesForArity;
            if ( . <= 2 || (callablesForArity = [2]) == null ) {
                throw .newArgumentError(2, . - 1);
            }
            callable = CallableSelector.matchingCallableArityTwo(callablesForArityarg0arg1);
            if ( callable == null ) {
                throw newErrorDueArgumentTypeMismatch(selfcallablesForArityarg0arg1);
            }
        }
        else {
            checkCallableArity(callable, 2);
        }
        return callable;
    }
    protected final JavaCallable findCallableArityThree(IRubyObject selfString nameIRubyObject arg0IRubyObject arg1IRubyObject arg2) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            // TODO: varargs?
            final JavaCallable[] callablesForArity;
            if ( . <= 3 || (callablesForArity = [3]) == null ) {
                throw .newArgumentError(3, . - 1);
            }
            callable = CallableSelector.matchingCallableArityThree(callablesForArityarg0arg1arg2);
            if ( callable == null ) {
                throw newErrorDueArgumentTypeMismatch(selfcallablesForArityarg0arg1arg2);
            }
        }
        else {
            checkCallableArity(callable, 3);
        }
        return callable;
    }
    protected final JavaCallable findCallableArityFour(IRubyObject selfString nameIRubyObject arg0IRubyObject arg1IRubyObject arg2IRubyObject arg3) {
        JavaCallable callable = this.;
        if ( callable == null ) {
            // TODO: varargs?
            final JavaCallable[] callablesForArity;
            if ( . <= 4 || (callablesForArity = [4]) == null ) {
                throw .newArgumentError(4, . - 1);
            }
            callable = CallableSelector.matchingCallableArityFour(callablesForArityarg0arg1arg2arg3);
            if ( callable == null ) {
                throw newErrorDueArgumentTypeMismatch(selfcallablesForArityarg0arg1arg2arg3);
            }
        }
        else {
            checkCallableArity(callable, 4);
        }
        return callable;
    }
    private void checkCallableArity(final JavaCallable callablefinal int expected) {
        final int arity = callable.getArity();
        if ( arity != expected ) throw .newArgumentError(expectedarity);
    }
    private JavaCallable someCallable() {
        if (  == null ) {
            for ( int i = 0; i < .i++ ) {
                JavaCallable[] callables = [i];
                if ( callables != null && callables.length > 0 ) {
                    for ( int j = 0; j < callables.lengthj++ ) {
                        if ( callables[j] != null ) return callables[j];
                    }
                }
            }
            return null// not expected to happen ...
        }
        return ;
    }
    private boolean isConstructor() {
        return someCallable() instanceof JavaConstructor;
    }
        final JavaCallable[] methodsIRubyObject... args) {
        final Class[] argTypes = new Class[args.length];
        for (int i = 0; i < args.lengthi++) {
            argTypes[i] = getClassargs[i] );
        }
        final StringBuilder error = new StringBuilder(64);
        error.append("no ");
        if ( isConstructor() ) error.append("constructor");
        else {
            org.jruby.javasupport.JavaMethod method = (org.jruby.javasupport.JavaMethodmethods[0];
            error.append("method '").appendmethod.getValue().getName() ).append("'");
        }
        error.append(" for arguments ");
        prettyParams(errorargTypes);
        error.append(" on ").appendformatReceiver(receiver) );
        if ( methods.length > 1 ) {
            error.append("\n  available overloads:");
            for (ParameterTypes method : methods) {
                Class<?>[] paramTypes = method.getParameterTypes();
                error.append("\n    "); prettyParamserrorparamTypes );
            }
        }
        // TODO should have been ArgumentError - might break users to refactor at this point
        return .newNameError(error.toString(), null);
    }
    private RaiseException newErrorDueNoMatchingCallable(final IRubyObject receiverfinal String name) {
        final StringBuilder error = new StringBuilder(48);
        error.append("no ");
        if ( isConstructor() ) error.append("constructor");
        else {
            error.append("method '").appendname ).append("'");
        }
        error.append(" (for zero arguments) on ").appendformatReceiver(receiver) );
        return .newArgumentErrorerror.toString() );
    }
    private static Class<?> getClass(final IRubyObject object) {
        if (object == nullreturn void.class;
        if (object instanceof ConcreteJavaProxy) {
            return ((ConcreteJavaProxyobject).getJavaClass();
        }
        return object.getClass();
    }
    private static String formatReceiver(final IRubyObject object) {
        if ( object instanceof RubyModule ) {
            return ((RubyModuleobject).getName();
        }
        return object.getMetaClass().getRealClass().getName();
    }
New to GrepCode? Check out our FAQ X