// Copyright (c) 2003-present, Jodd Team (http://jodd.org) // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. package jodd.proxetta; import jodd.proxetta.fixtures.data.*; import jodd.proxetta.impl.WrapperProxetta; import jodd.proxetta.impl.WrapperProxettaBuilder; import jodd.proxetta.pointcuts.ProxyPointcutSupport; import org.junit.Before; import org.junit.Test; import java.lang.reflect.Method; import static org.junit.Assert.*; public class WrapperTest { @Before public void setUp() throws Exception { StatCounter.counter = 0; } @Test public void testClassWrapper() throws Exception { Calc calc = new CalcImpl(); WrapperProxetta proxetta = WrapperProxetta.withAspects(new ProxyAspect(StatCounterAdvice.class, new ProxyPointcutSupport() { public boolean apply(MethodInfo methodInfo) { return !isRootMethod(methodInfo) && isPublic(methodInfo); } })); // proxetta.setDebugFolder("d:\\"); // wrapper over CLASS // resulting object has ALL interfaces // resulting object wraps ALL target class methods WrapperProxettaBuilder builder = proxetta.builder(calc.getClass()); Class calc2Class = builder.define(); Object object = calc2Class.newInstance(); assertTrue(object instanceof Calc); assertEquals(CalcImpl.class, ProxettaUtil.getTargetClass(object.getClass())); assertEquals(1, calc2Class.getInterfaces().length); builder.injectTargetIntoWrapper(calc, object); assertEquals(1, StatCounter.counter); // counter in static block !!! Method method = calc2Class.getMethod("hello"); assertNotNull(method); method.invoke(object); assertEquals(2, StatCounter.counter); method = calc2Class.getMethod("calculate", int.class, int.class); assertNotNull(method); Integer result = (Integer) method.invoke(object, 3, 7); assertEquals(10, result.intValue()); assertEquals(3, StatCounter.counter); assertNotNull(calc2Class.getMethod("customMethod")); } @Test public void testClassWrapperCastToInterface() throws Exception { Calc calc = new CalcImpl(); WrapperProxetta proxetta = WrapperProxetta.withAspects(new ProxyAspect(StatCounterAdvice.class, new ProxyPointcutSupport() { public boolean apply(MethodInfo methodInfo) { return !isRootMethod(methodInfo) && isPublic(methodInfo); } })); // proxetta.setDebugFolder("d:\\"); // wrapper over CLASS casted to interface, // resulting object has ONE interface // ALL target methods are wrapped WrapperProxettaBuilder builder = proxetta.builder(calc.getClass(), Calc.class, ".CalcImpl2"); Class<Calc> calc2Class = builder.define(); Calc calc2 = calc2Class.newInstance(); builder.injectTargetIntoWrapper(calc, calc2); assertEquals(1, StatCounter.counter); // counter in static block !!! calc2.hello(); assertEquals(2, StatCounter.counter); assertEquals(10, calc2.calculate(3, 7)); assertEquals(3, StatCounter.counter); assertNotNull(calc2Class.getMethod("customMethod")); } @Test public void testInterfaceWrapper() throws Exception { Calc calc = new CalcImpl(); WrapperProxetta proxetta = WrapperProxetta.withAspects(new ProxyAspect(StatCounterAdvice.class, new ProxyPointcutSupport() { public boolean apply(MethodInfo methodInfo) { return isTopLevelMethod(methodInfo) && isPublic(methodInfo); } })); //proxetta.setDebugFolder("/Users/igor"); // wrapper over INTERFACE // resulting object has ONE interface // only interface methods are wrapped WrapperProxettaBuilder builder = proxetta.builder(Calc.class, ".CalcImpl3"); Class<Calc> calc2Class = builder.define(); Calc calc2 = calc2Class.newInstance(); builder.injectTargetIntoWrapper(calc, calc2); assertEquals(1, StatCounter.counter); // counter in static block !!! calc2.hello(); assertEquals(2, StatCounter.counter); assertEquals(10, calc2.calculate(3, 7)); assertEquals(3, StatCounter.counter); try { calc2Class.getMethod("customMethod"); fail(); } catch (Exception ex) { } } @Test public void testPartialMethodsWrapped() throws Exception { Calc calc = new CalcSuperImpl(); WrapperProxetta proxetta = WrapperProxetta.withAspects(new ProxyAspect(StatCounterAdvice.class, new ProxyPointcutSupport() { public boolean apply(MethodInfo methodInfo) { return isPublic(methodInfo) && (methodInfo.getMethodName().equals("hello") || methodInfo.getMethodName().equals("ola")); } })); // proxetta.setDebugFolder("d:\\"); WrapperProxettaBuilder builder = proxetta.builder(CalcSuper.class); Class<CalcSuper> calc2Class = builder.define(); CalcSuper calc2 = calc2Class.newInstance(); builder.injectTargetIntoWrapper(calc, calc2); assertEquals(1, StatCounter.counter); // counter in static block !!! calc2.hello(); assertEquals(2, StatCounter.counter); assertEquals(10, calc2.calculate(3, 7)); assertEquals(2, StatCounter.counter); // counter not called in calculate! calc2.ola(); assertEquals(3, StatCounter.counter); calc2.superhi(); calc2.maybe(4, 5); calc2.calculate(4, 5); assertEquals(3, StatCounter.counter); } @Test public void testNoPointcutMatched() throws Exception { Calc calc = new CalcSuperImpl(); WrapperProxetta proxetta = WrapperProxetta.withAspects(new ProxyAspect(StatCounterAdvice.class, new ProxyPointcutSupport() { public boolean apply(MethodInfo methodInfo) { return false; } })); // proxetta.setDebugFolder("d:\\"); WrapperProxettaBuilder builder = proxetta.builder(CalcSuper.class, ".CalcSuper22"); Class<CalcSuper> calc2Class = builder.define(); CalcSuper calc2 = calc2Class.newInstance(); builder.injectTargetIntoWrapper(calc, calc2); assertEquals(1, StatCounter.counter); // counter in static block !!! calc2.hello(); assertEquals(1, StatCounter.counter); assertEquals(10, calc2.calculate(3, 7)); assertEquals(1, StatCounter.counter); // counter not called in calculate! calc2.ola(); assertEquals(1, StatCounter.counter); calc2.superhi(); calc2.maybe(4, 5); calc2.calculate(4, 5); assertEquals(1, StatCounter.counter); } }