/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.mule.model; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mule.runtime.api.message.Message.of; import static org.mule.runtime.core.api.Event.getCurrentEvent; import static org.mule.runtime.core.api.Event.setCurrentEvent; import static org.mule.tck.MuleTestUtils.getTestFlow; import org.mule.runtime.core.DefaultEventContext; import org.mule.runtime.core.DefaultMuleEventContext; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.MuleEventContext; import org.mule.runtime.core.api.construct.FlowConstruct; import org.mule.runtime.core.api.model.InvocationResult; import org.mule.runtime.core.api.model.resolvers.ReflectionEntryPointResolver; import org.mule.tck.junit4.AbstractMuleContextTestCase; import org.mule.tck.testmodels.fruit.Apple; import org.mule.tck.testmodels.fruit.Banana; import org.mule.tck.testmodels.fruit.Fruit; import org.mule.tck.testmodels.fruit.FruitBowl; import org.mule.tck.testmodels.fruit.FruitLover; import org.mule.tck.testmodels.fruit.Kiwi; import org.mule.tck.testmodels.fruit.Orange; import org.mule.tck.testmodels.fruit.WaterMelon; import java.lang.reflect.Method; import org.junit.Before; import org.junit.Test; import org.mockito.cglib.proxy.Enhancer; import org.mockito.cglib.proxy.MethodInterceptor; import org.mockito.cglib.proxy.MethodProxy; public class ReflectionEntryPointResolverTestCase extends AbstractMuleContextTestCase { private FlowConstruct flowConstruct; @Before public void before() throws Exception { flowConstruct = getTestFlow(muleContext); } @Test public void testExplicitMethodMatch() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of("blah")) .build(); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(new WaterMelon(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); } @Test public void testExplicitMethodMatchComplexObject() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of(new FruitLover("Mmmm"))) .build(); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); } @Test public void testMethodMatchWithArguments() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of(new Object[] {new Apple(), new Banana()})) .build()); InvocationResult result = resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); assertTrue(result.getResult() instanceof Fruit[]); // test that the correct methd was called assertTrue(((Fruit[]) result.getResult())[0] instanceof Apple); assertTrue(((Fruit[]) result.getResult())[1] instanceof Banana); assertEquals("addAppleAndBanana", result.getMethodCalled()); eventContext = new DefaultMuleEventContext(flowConstruct, Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of(new Object[] {new Banana(), new Apple()})) .build()); result = resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); assertTrue(result.getResult() instanceof Fruit[]); assertTrue(((Fruit[]) result.getResult())[0] instanceof Banana); assertTrue(((Fruit[]) result.getResult())[1] instanceof Apple); assertEquals("addBananaAndApple", result.getMethodCalled()); } @Test public void testExplicitMethodMatchSetArrayFail() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of(new Fruit[] {new Apple(), new Orange()})) .build(); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent())); assertEquals("Test should have failed because the arguments were not wrapped properly: ", result.getState(), InvocationResult.State.FAILED); } @Test public void testExplicitMethodMatchSetArrayPass() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of(new Object[] {new Fruit[] {new Apple(), new Orange()}})) .build(); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); } /** * Tests entrypoint discovery when there is more than one discoverable method with MuleEventContext parameter. */ @Test public void testFailEntryPointMultiplePayloadMatches() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event testEvent = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)) .message(of("Hello")).build(); setCurrentEvent(testEvent); MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, getCurrentEvent()); InvocationResult result = resolver.invoke(new MultiplePayloadsTestObject(), eventContext, Event.builder(getCurrentEvent())); assertEquals(result.getState(), InvocationResult.State.FAILED); } @Test public void testMatchOnNoArgs() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)).message(of(null)).build(); // This should fail because the Kiwi.bite() method has a void return type, and by default // void methods are ignorred MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(new Kiwi(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.FAILED); resolver.setAcceptVoidMethods(true); result = resolver.invoke(new Kiwi(), eventContext, Event.builder(eventContext.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); assertEquals("bite", result.getMethodCalled()); } @Test public void testAnnotatedMethodOnProxyWithMethodSet() throws Exception { ReflectionEntryPointResolver resolver = new ReflectionEntryPointResolver(); Enhancer e = new Enhancer(); e.setSuperclass(WaterMelon.class); e.setCallback(new DummyMethodCallback()); Object proxy = e.create(); final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION)).message(of("Blah")).build(); MuleEventContext context = new DefaultMuleEventContext(flowConstruct, event); InvocationResult result = resolver.invoke(proxy, context, Event.builder(context.getEvent())); assertEquals(result.getState(), InvocationResult.State.SUCCESSFUL); } private class DummyMethodCallback implements MethodInterceptor { public DummyMethodCallback() { super(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before: " + method.getName()); Object r = proxy.invokeSuper(obj, args); System.out.println("after: " + method.getName()); // Add handler code here return r; } } }