/** * This method is a default implementation for the invoke method given in InvocationHandler. Any * call to a method with a declaring class that is not Object, excluding toString() and default * methods is redirected to invokeCustom. * * <p>Methods like equals and hashcode are called on the class itself instead of the delegate * because they are considered fundamental methods that should not be overwritten. The toString() * method gets special treatment as it is deemed to be a method that you might wish to override * when called from Groovy. Interface default methods from Java 8 on the other hand are considered * being default implementations you don't normally want to change. So they are called directly * too * * <p>In many scenarios, it is better to overwrite the invokeCustom method where the core Object * related methods are filtered out. * * @param proxy the proxy * @param method the method * @param args the arguments * @return the result of the invocation by method or delegate * @throws Throwable if caused by the delegate or the method * @see #invokeCustom(Object, Method, Object[]) * @see InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { VMPlugin plugin = VMPluginFactory.getPlugin(); if (plugin.getVersion() >= 7 && isDefaultMethod(method)) { Object handle = handleCache.get(method); if (handle == null) { handle = plugin.getInvokeSpecialHandle(method, proxy); handleCache.put(method, handle); } return plugin.invokeHandle(handle, args); } if (!checkMethod(method)) { try { if (method.getDeclaringClass() == GroovyObject.class) { if ("getMetaClass".equals(method.getName())) { return getMetaClass(proxy); } else if ("setMetaClass".equals(method.getName())) { return setMetaClass((MetaClass) args[0]); } } return invokeCustom(proxy, method, args); } catch (GroovyRuntimeException gre) { throw ScriptBytecodeAdapter.unwrap(gre); } } try { return method.invoke(this, args); } catch (InvocationTargetException ite) { throw ite.getTargetException(); } }
public Object callConstructor(Object receiver, Object[] args) throws Throwable { try { if (receiver == metaClass.getTheClass() && version == classInfo.getVersion()) // metaClass still be valid return metaClass.invokeConstructor(args); else return CallSiteArray.defaultCallConstructor(this, receiver, args); } catch (GroovyRuntimeException gre) { throw ScriptBytecodeAdapter.unwrap(gre); } }
/** * Asserts that the given code closure fails when it is evaluated and that a particular Exception * type can be attributed to the cause. The expected exception class is compared recursively with * any nested exceptions using getCause() until either a match is found or no more nested * exceptions exist. * * <p>If a match is found, the matching exception is returned otherwise the method will fail. * * @param expectedCause the class of the expected exception * @param code the closure that should fail * @return the cause */ public static Throwable shouldFailWithCause(Class expectedCause, Closure code) { if (expectedCause == null) { fail("The expectedCause class cannot be null"); } Throwable cause = null; Throwable orig = null; int level = 0; try { code.call(); } catch (GroovyRuntimeException gre) { orig = ScriptBytecodeAdapter.unwrap(gre); cause = orig.getCause(); } catch (Throwable e) { orig = e; cause = orig.getCause(); } if (orig != null && cause == null) { fail( "Closure " + code + " was expected to fail due to a nested cause of type " + expectedCause.getName() + " but instead got a direct exception of type " + orig.getClass().getName() + " with no nested cause(s). Code under test has a bug or perhaps you meant shouldFail?"); } while (cause != null && !expectedCause.isInstance(cause) && cause != cause.getCause() && level < MAX_NESTED_EXCEPTIONS) { cause = cause.getCause(); level++; } if (orig == null) { fail( "Closure " + code + " should have failed with an exception having a nested cause of type " + expectedCause.getName()); } else if (cause == null || !expectedCause.isInstance(cause)) { fail( "Closure " + code + " should have failed with an exception having a nested cause of type " + expectedCause.getName() + ", instead found these Exceptions:\n" + buildExceptionList(orig)); } return cause; }
/** * Asserts that the given code closure fails when it is evaluated * * @param code the code expected to fail * @return the caught exception */ public static Throwable shouldFail(Closure code) { boolean failed = false; Throwable th = null; try { code.call(); } catch (GroovyRuntimeException gre) { failed = true; th = ScriptBytecodeAdapter.unwrap(gre); } catch (Throwable e) { failed = true; th = e; } assertTrue("Closure " + code + " should have failed", failed); return th; }
/** * Asserts that the given code closure fails when it is evaluated and that a particular type of * exception is thrown. * * @param clazz the class of the expected exception * @param code the closure that should fail * @return the caught exception */ public static Throwable shouldFail(Class clazz, Closure code) { Throwable th = null; try { code.call(); } catch (GroovyRuntimeException gre) { th = ScriptBytecodeAdapter.unwrap(gre); } catch (Throwable e) { th = e; } if (th == null) { fail("Closure " + code + " should have failed with an exception of type " + clazz.getName()); } else if (!clazz.isInstance(th)) { fail( "Closure " + code + " should have failed with an exception of type " + clazz.getName() + ", instead got Exception " + th); } return th; }