static MethodHandle adjustArity(MethodHandle mh, int arity) { MethodType mt = mh.type(); int posArgs = mt.parameterCount() - 1; Class<?> reptype = mt.parameterType(posArgs).getComponentType(); MethodType mt1 = mt.dropParameterTypes(posArgs, posArgs+1); while (mt1.parameterCount() < arity) { Class<?> pt = reptype; if (pt == Object.class && posArgs > 0) // repeat types cyclically if possible: pt = mt1.parameterType(mt1.parameterCount() - posArgs); mt1 = mt1.appendParameterTypes(pt); } try { return mh.asType(mt1); } catch (WrongMethodTypeException | IllegalArgumentException ex) { throw new IllegalArgumentException("cannot convert to type "+mt1+" from "+mh, ex); } }
@Override public void invoke(Object[] parameters) { try { methodHandle.invokeExact(parameters); } catch (WrongMethodTypeException e) { throw new TomokoException("Problem with Tomoko itself.", e); } catch (Throwable throwable) { if (throwable instanceof Error) { throw (Error) throwable; } else if (throwable instanceof RuntimeException) { throw (RuntimeException) throwable; } else { throw new HandlerExecutionException((Exception) throwable); } } }
@Override public WorkberchGenericBolt buildBolt(final String guid) { WorkberchGenericBolt ret = null; switch (nodeType) { case XPATH: ret = new XPathBolt(guid, getInputs(), getOutputs(), config); break; case REST: ret = new RestBolt(guid, getInputs(), getOutputs(), config); break; case BEANSHELL: ret = new BeanshellBolt(guid, getInputs(), getOutputs(), config); break; default: throw new WrongMethodTypeException("No se ha implementado el tipo de processor de taverna: " + nodeType); } return ret; }
public static WorkberchNodeInput processor2NodeInput(final Processor processor, final Configuration config) { final String processorType = config.getType().toString(); DataGenerator dg = null; switch (TavernaNodeType.fromString(processorType)) { case TEXT_CONSTANT: dg = new TextDataGenerator(config.getJson().get("string").asText()); break; default: throw new WrongMethodTypeException("No se ha implementado el tipo de processor de taverna: " + processorType); } final List<String> outputFields = new ArrayList<String>(); for (final OutputProcessorPort outputPort : processor.getOutputPorts()) { outputFields.add(processor.getName() + WorkberchConstants.NAME_DELIMITER + outputPort.getName()); } // FIXME: El parametro isSimple en la creacion de este nodo podria ser // mejorado para los casos que // se pueda determinar si esto envia solo un valor. return new WorkberchNodeInput(processor.getName(), dg, outputFields); }
private void testArities(Class<? extends Object[]> cls, int minArity, int maxArity, int iterations) throws Throwable { boolean verbose = (cls == Object[].class); for (int arity = minArity; arity <= maxArity; arity++) { if (verbose) System.out.println("arity="+arity); MethodHandle mh = MH_hashArguments(cls, arity); MethodHandle mh_VA = mh.asSpreader(cls, arity); assert(mh_VA.type().parameterType(0) == cls); testArities(cls, arity, iterations, verbose, mh, mh_VA); if (cls != Object[].class) { // mh_CA will collect arguments of a particular type and pass them to mh_VA MethodHandle mh_CA = mh_VA.asCollector(cls, arity); MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity); try { mh_VA2.invokeWithArguments(new Object[arity]); throw new AssertionError("should not reach"); } catch (ClassCastException | WrongMethodTypeException ex) { } assert(mh_CA.type().equals(mh.type())); assert(mh_VA2.type().equals(mh_VA.type())); testArities(cls, arity, iterations, false, mh_CA, mh_VA2); } } }
private static MethodHandle forSpreadCall(MethodHandle mh, MethodType type) { int expectedParameters = mh.type().parameterCount(); int actualParameters = type.parameterCount(); if (!mh.isVarargsCollector() || !mh.type().parameterType(expectedParameters - 1).equals(Object[].class)) { throw new WrongMethodTypeException("Not Object[] var-args collector"); } if (expectedParameters > actualParameters) { throw new WrongMethodTypeException("Too few arguments"); } if (expectedParameters < actualParameters) { int fixedCount = actualParameters - expectedParameters; int firstFixed = expectedParameters - 1; List<Class<?>> fixed = type.parameterList().subList(firstFixed, firstFixed + fixedCount); mh = MethodHandles.collectArguments(mh, firstFixed, combineArraysMH); mh = MethodHandles.collectArguments(mh, firstFixed, toObjectArray(fixed)); } return mh.asType(type); }
private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) { try { MethodHandles.explicitCastArguments(mh, mt); throw new AssertionError("Expected WrongMethodTypeException is not thrown"); } catch (WrongMethodTypeException wmte) { if (VERBOSE) { System.out.printf("Expected exception %s: %s\n", wmte.getClass(), wmte.getMessage()); } } }
private void testArities(Class<? extends Object[]> cls, int minArity, int maxArity, int iterations) throws Throwable { boolean verbose = (cls == Object[].class); for (int arity = minArity; arity <= maxArity; arity++) { if (verbose) System.out.println("arity="+arity); MethodHandle mh = MH_hashArguments(cls, arity); MethodHandle mh_VA = mh.asSpreader(cls, arity); assert(mh_VA.type().parameterType(0) == cls); testArities(cls, arity, iterations, verbose, mh, mh_VA); // mh_CA will collect arguments of a particular type and pass them to mh_VA MethodHandle mh_CA = mh_VA.asCollector(cls, arity); MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity); assert(mh_CA.type().equals(mh.type())); assert(mh_VA2.type().equals(mh_VA.type())); if (cls != Object[].class) { try { mh_VA2.invokeWithArguments(new Object[arity]); throw new AssertionError("should not reach"); } catch (ClassCastException | WrongMethodTypeException ex) { } } int iterations_VA = iterations / 100; testArities(cls, arity, iterations_VA, false, mh_CA, mh_VA2); } }
private void testArities(Class<? extends Object[]> cls, int minArity, int maxArity, int iterations) throws Throwable { boolean verbose = (cls == Object[].class); for (int arity = minArity; arity <= maxArity; arity++) { if (verbose) System.out.println("arity="+arity); MethodHandle mh = MH_hashArguments(cls, arity); MethodHandle mh_VA = mh.asSpreader(cls, arity); MethodHandle mh_VA_h = mh.asSpreader(0, cls, arity-1); assert(mh_VA.type().parameterType(0) == cls); assert(mh_VA_h.type().parameterType(0) == cls); testArities(cls, arity, iterations, verbose, mh, mh_VA, mh_VA_h); // mh_CA will collect arguments of a particular type and pass them to mh_VA MethodHandle mh_CA = mh_VA.asCollector(cls, arity); MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity); MethodHandle mh_VA2_h = mh_CA.asSpreader(0, cls, arity-1); assert(mh_CA.type().equals(mh.type())); assert(mh_VA2.type().equals(mh_VA.type())); if (cls != Object[].class) { try { mh_VA2.invokeWithArguments(new Object[arity]); throw new AssertionError("should not reach"); } catch (ClassCastException | WrongMethodTypeException ex) { } } int iterations_VA = iterations / 100; testArities(cls, arity, iterations_VA, false, mh_CA, mh_VA2, mh_VA2_h); } }
@Test(expectedExceptions = WrongMethodTypeException.class) public void test_asInterfaceInstance_wrong_target_type() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle handle = lookup.findStatic(MyCallable.class, "hello", genericMethodType(0)); assertThat((String) handle.invoke(), is("Hello!")); Predefined.asInterfaceInstance(ActionListener.class, new FunctionReference(handle)); }
@Test(expectedExceptions = WrongMethodTypeException.class) public void invoker_call_any_type_mismatch() throws Throwable { DynamicObject object = new DynamicObject(); MethodHandle invoker = object.invoker("foo", genericMethodType(4)); object.define("foo", new FunctionReference(lookup().findStatic(DynamicObjectTest.class, "inAList", genericMethodType(3)))); invoker.invoke(object, "plop", "da", "plop"); }
/** * Create a method handle that will apply all transformations specified by the current method builder * and then call the {@code method} method. * This method uses a cache if the method is a virtual method (either on class or interface) * * @param lookup the lookup object used to find the @code method} * @param method the method called at the end of the transformation. * @return a new method handle constructed by applying all transformations on the target method. * @throws NoSuchMethodException throws is a method is not visible. * @throws NoSuchFieldException throws if a field is not visible. * @throws IllegalAccessException throws if a type or a member of a type is not visible. */ public MethodHandle unreflect(Lookup lookup, Method method) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { MethodHandle target = lookup.unreflect(method); MethodType targetType = target.type(); if (!targetType.equals(sig)) { throw new WrongMethodTypeException("target type " + targetType + " is not equals to current type " + sig); } int modifiers = method.getModifiers(); if (!Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers)) { // can be virtual target = new InliningCacheCallSite(target).dynamicInvoker(); } return call(target); }
@Test public void testBoundaryValues() throws Throwable { for (int badArity : new int[]{ -1, MAX_JVM_ARITY+1, MAX_JVM_ARITY }) { try { MethodHandle badmh = MH_hashArguments(badArity); throw new AssertionError("should not be able to build a 255-arity MH: "+badmh); } catch (IllegalArgumentException | WrongMethodTypeException ex) { System.out.println("OK: "+ex); } } }
public void testDynamicWrongArgs() { expectScriptThrows(WrongMethodTypeException.class, () -> { exec("def x = new ArrayList(); return x.get('bogus');"); }); }
public void testDynamicArrayWrongIndex() { expectScriptThrows(WrongMethodTypeException.class, () -> { exec("def x = new long[1]; x[0]=1; return x['bogus'];"); }); }
public void testDynamicListWrongIndex() { expectScriptThrows(WrongMethodTypeException.class, () -> { exec("def x = new ArrayList(); x.add('foo'); return x['bogus'];"); }); }
private static void assertType(final MethodHandle mh, final MethodType type) { if(!mh.type().equals(type)) { throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type()); } }
@Override List<Class<? extends Throwable>> expectedThrowableClasses() { return List.of(BootstrapMethodError.class, WrongMethodTypeException.class); }
static void checkWMTE(ThrowingRunnable r) { checkWithThrowable(WrongMethodTypeException.class, null, r); }
static void checkWMTE(Object message, ThrowingRunnable r) { checkWithThrowable(WrongMethodTypeException.class, message, r); }
Class<? extends Throwable> getWMTEOOrOther(Class<? extends Throwable> c) { return f.isExact ? WrongMethodTypeException.class : c; }
@Test(expectedExceptions = {WrongMethodTypeException.class}) public static void testAsSpreaderIllegalMethodType() { MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class); MethodHandle s = h.asSpreader(String[].class, 1); }