diff --git a/org.springframework.aop/.classpath b/org.springframework.aop/.classpath index ebaf6620e39..b0130448ba2 100644 --- a/org.springframework.aop/.classpath +++ b/org.springframework.aop/.classpath @@ -7,6 +7,7 @@ + diff --git a/org.springframework.aop/aop.iml b/org.springframework.aop/aop.iml index c0a0865f327..fa9b87435ef 100644 --- a/org.springframework.aop/aop.iml +++ b/org.springframework.aop/aop.iml @@ -99,6 +99,17 @@ + + + + + + + + + + + diff --git a/org.springframework.aop/ivy.xml b/org.springframework.aop/ivy.xml index 3a29401a44b..53297d90bf4 100644 --- a/org.springframework.aop/ivy.xml +++ b/org.springframework.aop/ivy.xml @@ -33,6 +33,7 @@ + diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/framework/MethodCounter.java b/org.springframework.aop/src/test/java/org/springframework/aop/framework/MethodCounter.java new file mode 100644 index 00000000000..d3030ffe8e0 --- /dev/null +++ b/org.springframework.aop/src/test/java/org/springframework/aop/framework/MethodCounter.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.aop.framework; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.HashMap; + +/** + * Useful abstract superclass for counting advices etc. + * + * @author Rod Johnson + */ +public class MethodCounter implements Serializable { + + /** Method name --> count, does not understand overloading */ + private HashMap map = new HashMap(); + + private int allCount; + + protected void count(Method m) { + count(m.getName()); + } + + protected void count(String methodName) { + Integer i = (Integer) map.get(methodName); + i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1); + map.put(methodName, i); + ++allCount; + } + + public int getCalls(String methodName) { + Integer i = (Integer) map.get(methodName); + return (i != null ? i.intValue() : 0); + } + + public int getCalls() { + return allCount; + } + + /** + * A bit simplistic: just wants the same class. + * Doesn't worry about counts. + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object other) { + return (other != null && other.getClass() == this.getClass()); + } + + public int hashCode() { + return getClass().hashCode(); + } + +} diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java similarity index 64% rename from org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java rename to org.springframework.aop/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java index 176da331750..9f27eccba5a 100644 --- a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java +++ b/org.springframework.aop/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java @@ -16,24 +16,32 @@ package org.springframework.aop.framework.adapter; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.FileNotFoundException; +import java.io.IOException; import java.lang.reflect.Method; import java.rmi.RemoteException; -import javax.servlet.ServletException; import javax.transaction.TransactionRolledbackException; -import junit.framework.TestCase; import org.aopalliance.intercept.MethodInvocation; -import org.easymock.MockControl; - +import org.junit.Test; import org.springframework.aop.ThrowsAdvice; import org.springframework.aop.framework.MethodCounter; /** * @author Rod Johnson + * @author Chris Beams */ -public class ThrowsAdviceInterceptorTests extends TestCase { +public class ThrowsAdviceInterceptorTests { + @Test public void testNoHandlerMethods() { Object o = new Object(); try { @@ -45,30 +53,28 @@ public class ThrowsAdviceInterceptorTests extends TestCase { } } + @Test public void testNotInvoked() throws Throwable { MyThrowsHandler th = new MyThrowsHandler(); ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th); Object ret = new Object(); - MockControl mc = MockControl.createControl(MethodInvocation.class); - MethodInvocation mi = (MethodInvocation) mc.getMock(); - mi.proceed(); - mc.setReturnValue(ret, 1); - mc.replay(); + MethodInvocation mi = createMock(MethodInvocation.class); + expect(mi.proceed()).andReturn(ret); + replay(mi); assertEquals(ret, ti.invoke(mi)); assertEquals(0, th.getCalls()); - mc.verify(); + verify(mi); } + @Test public void testNoHandlerMethodForThrowable() throws Throwable { MyThrowsHandler th = new MyThrowsHandler(); ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th); assertEquals(2, ti.getHandlerMethodCount()); Exception ex = new Exception(); - MockControl mc = MockControl.createControl(MethodInvocation.class); - MethodInvocation mi = (MethodInvocation) mc.getMock(); - mi.proceed(); - mc.setThrowable(ex); - mc.replay(); + MethodInvocation mi = createMock(MethodInvocation.class); + expect(mi.proceed()).andThrow(ex); + replay(mi); try { ti.invoke(mi); fail(); @@ -77,24 +83,20 @@ public class ThrowsAdviceInterceptorTests extends TestCase { assertEquals(ex, caught); } assertEquals(0, th.getCalls()); - mc.verify(); + verify(mi); } + @Test public void testCorrectHandlerUsed() throws Throwable { MyThrowsHandler th = new MyThrowsHandler(); ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th); - ServletException ex = new ServletException(); - MockControl mc = MockControl.createControl(MethodInvocation.class); - MethodInvocation mi = (MethodInvocation) mc.getMock(); - mi.getMethod(); - mc.setReturnValue(Object.class.getMethod("hashCode", (Class[]) null), 1); - mi.getArguments(); - mc.setReturnValue(null); - mi.getThis(); - mc.setReturnValue(new Object()); - mi.proceed(); - mc.setThrowable(ex); - mc.replay(); + FileNotFoundException ex = new FileNotFoundException(); + MethodInvocation mi = createMock(MethodInvocation.class); + expect(mi.getMethod()).andReturn(Object.class.getMethod("hashCode", (Class[]) null)); + expect(mi.getArguments()).andReturn(null); + expect(mi.getThis()).andReturn(new Object()); + expect(mi.proceed()).andThrow(ex); + replay(mi); try { ti.invoke(mi); fail(); @@ -103,20 +105,19 @@ public class ThrowsAdviceInterceptorTests extends TestCase { assertEquals(ex, caught); } assertEquals(1, th.getCalls()); - assertEquals(1, th.getCalls("servletException")); - mc.verify(); + assertEquals(1, th.getCalls("ioException")); + verify(mi); } + @Test public void testCorrectHandlerUsedForSubclass() throws Throwable { MyThrowsHandler th = new MyThrowsHandler(); ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th); // Extends RemoteException TransactionRolledbackException ex = new TransactionRolledbackException(); - MockControl mc = MockControl.createControl(MethodInvocation.class); - MethodInvocation mi = (MethodInvocation) mc.getMock(); - mi.proceed(); - mc.setThrowable(ex); - mc.replay(); + MethodInvocation mi = createMock(MethodInvocation.class); + expect(mi.proceed()).andThrow(ex); + replay(mi); try { ti.invoke(mi); fail(); @@ -126,25 +127,27 @@ public class ThrowsAdviceInterceptorTests extends TestCase { } assertEquals(1, th.getCalls()); assertEquals(1, th.getCalls("remoteException")); - mc.verify(); + verify(mi); } + @Test public void testHandlerMethodThrowsException() throws Throwable { final Throwable t = new Throwable(); + + @SuppressWarnings("serial") MyThrowsHandler th = new MyThrowsHandler() { public void afterThrowing(RemoteException ex) throws Throwable { super.afterThrowing(ex); throw t; } }; + ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th); // Extends RemoteException TransactionRolledbackException ex = new TransactionRolledbackException(); - MockControl mc = MockControl.createControl(MethodInvocation.class); - MethodInvocation mi = (MethodInvocation) mc.getMock(); - mi.proceed(); - mc.setThrowable(ex); - mc.replay(); + MethodInvocation mi = createMock(MethodInvocation.class); + expect(mi.proceed()).andThrow(ex); + replay(mi); try { ti.invoke(mi); fail(); @@ -154,44 +157,23 @@ public class ThrowsAdviceInterceptorTests extends TestCase { } assertEquals(1, th.getCalls()); assertEquals(1, th.getCalls("remoteException")); - mc.verify(); + verify(mi); } - public static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice { + @SuppressWarnings("serial") + private static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice { // Full method signature - public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - count("servletException"); - } + public void afterThrowing(Method m, Object[] args, Object target, IOException ex) { + count("ioException"); + } public void afterThrowing(RemoteException ex) throws Throwable { count("remoteException"); - } + } /** Not valid, wrong number of arguments */ public void afterThrowing(Method m, Exception ex) throws Throwable { throw new UnsupportedOperationException("Shouldn't be called"); - } + } } - public interface IEcho { - int echoException(int i, Throwable t) throws Throwable; - int getA(); - void setA(int a); - } - - public static class Echo implements IEcho { - private int a; - - public int echoException(int i, Throwable t) throws Throwable { - if (t != null) - throw t; - return i; - } - public void setA(int a) { - this.a = a; - } - public int getA() { - return a; - } - } - } diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java index 9ce0ed576b1..b87c121c37c 100644 --- a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java +++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java @@ -29,16 +29,15 @@ import javax.servlet.ServletException; import javax.transaction.TransactionRequiredException; import junit.framework.TestCase; + import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; - import org.springframework.aop.Advisor; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.DynamicIntroductionAdvice; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.aop.TargetSource; -import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests; import org.springframework.aop.interceptor.DebugInterceptor; import org.springframework.aop.interceptor.ExposeInvocationInterceptor; import org.springframework.aop.interceptor.NopInterceptor; @@ -1463,20 +1462,20 @@ public abstract class AbstractAopProxyTests extends TestCase { public void testThrowsAdvisorIsInvoked() throws Throwable { // Reacts to ServletException and RemoteException - ThrowsAdviceInterceptorTests.MyThrowsHandler th = new ThrowsAdviceInterceptorTests.MyThrowsHandler(); + MyThrowsHandler th = new MyThrowsHandler(); Advisor matchesEchoInvocations = new StaticMethodMatcherPointcutAdvisor(th) { public boolean matches(Method m, Class targetClass) { return m.getName().startsWith("echo"); } }; - ThrowsAdviceInterceptorTests.Echo target = new ThrowsAdviceInterceptorTests.Echo(); + Echo target = new Echo(); target.setA(16); ProxyFactory pf = new ProxyFactory(target); pf.addAdvice(new NopInterceptor()); pf.addAdvisor(matchesEchoInvocations); assertEquals("Advisor was added", matchesEchoInvocations, pf.getAdvisors()[1]); - ThrowsAdviceInterceptorTests.IEcho proxied = (ThrowsAdviceInterceptorTests.IEcho) createProxy(pf); + IEcho proxied = (IEcho) createProxy(pf); assertEquals(0, th.getCalls()); assertEquals(target.getA(), proxied.getA()); assertEquals(0, th.getCalls()); @@ -1503,14 +1502,14 @@ public abstract class AbstractAopProxyTests extends TestCase { public void testAddThrowsAdviceWithoutAdvisor() throws Throwable { // Reacts to ServletException and RemoteException - ThrowsAdviceInterceptorTests.MyThrowsHandler th = new ThrowsAdviceInterceptorTests.MyThrowsHandler(); + MyThrowsHandler th = new MyThrowsHandler(); - ThrowsAdviceInterceptorTests.Echo target = new ThrowsAdviceInterceptorTests.Echo(); + Echo target = new Echo(); target.setA(16); ProxyFactory pf = new ProxyFactory(target); pf.addAdvice(new NopInterceptor()); pf.addAdvice(th); - ThrowsAdviceInterceptorTests.IEcho proxied = (ThrowsAdviceInterceptorTests.IEcho) createProxy(pf); + IEcho proxied = (IEcho) createProxy(pf); assertEquals(0, th.getCalls()); assertEquals(target.getA(), proxied.getA()); assertEquals(0, th.getCalls()); @@ -1536,7 +1535,6 @@ public abstract class AbstractAopProxyTests extends TestCase { assertEquals(1, th.getCalls("remoteException")); } - private static class CheckMethodInvocationIsSameInAndOutInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation mi) throws Throwable { diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Echo.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Echo.java new file mode 100644 index 00000000000..da03878e47f --- /dev/null +++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Echo.java @@ -0,0 +1,20 @@ +/** + * + */ +package org.springframework.aop.framework; + +class Echo implements IEcho { + private int a; + + public int echoException(int i, Throwable t) throws Throwable { + if (t != null) + throw t; + return i; + } + public void setA(int a) { + this.a = a; + } + public int getA() { + return a; + } +} \ No newline at end of file diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IEcho.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IEcho.java new file mode 100644 index 00000000000..78f4b0e927c --- /dev/null +++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IEcho.java @@ -0,0 +1,10 @@ +/** + * + */ +package org.springframework.aop.framework; + +interface IEcho { + int echoException(int i, Throwable t) throws Throwable; + int getA(); + void setA(int a); +} \ No newline at end of file diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MyThrowsHandler.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MyThrowsHandler.java new file mode 100644 index 00000000000..48c59a5e000 --- /dev/null +++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MyThrowsHandler.java @@ -0,0 +1,25 @@ +/** + * + */ +package org.springframework.aop.framework; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.rmi.RemoteException; + +import org.springframework.aop.ThrowsAdvice; + +@SuppressWarnings("serial") class MyThrowsHandler extends MethodCounter implements ThrowsAdvice { + // Full method signature + public void afterThrowing(Method m, Object[] args, Object target, IOException ex) { + count("ioException"); + } + public void afterThrowing(RemoteException ex) throws Throwable { + count("remoteException"); + } + + /** Not valid, wrong number of arguments */ + public void afterThrowing(Method m, Exception ex) throws Throwable { + throw new UnsupportedOperationException("Shouldn't be called"); + } +} \ No newline at end of file diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java index 6a037a26cd7..d5596967088 100644 --- a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java +++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java @@ -31,7 +31,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.ClassFilter; import org.springframework.aop.IntroductionAdvisor; import org.springframework.aop.IntroductionInterceptor; -import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests; import org.springframework.aop.interceptor.DebugInterceptor; import org.springframework.aop.interceptor.NopInterceptor; import org.springframework.aop.interceptor.SideEffectBean; @@ -404,11 +403,11 @@ public class ProxyFactoryBeanTests extends TestCase { public void testCanAddThrowsAdviceWithoutAdvisor() throws Throwable { BeanFactory f = new XmlBeanFactory(new ClassPathResource("throwsAdvice.xml", getClass())); - ThrowsAdviceInterceptorTests.MyThrowsHandler th = (ThrowsAdviceInterceptorTests.MyThrowsHandler) f.getBean("throwsAdvice"); + MyThrowsHandler th = (MyThrowsHandler) f.getBean("throwsAdvice"); CountingBeforeAdvice cba = (CountingBeforeAdvice) f.getBean("countingBeforeAdvice"); assertEquals(0, cba.getCalls()); assertEquals(0, th.getCalls()); - ThrowsAdviceInterceptorTests.IEcho echo = (ThrowsAdviceInterceptorTests.IEcho) f.getBean("throwsAdvised"); + IEcho echo = (IEcho) f.getBean("throwsAdvised"); int i = 12; echo.setA(i); assertEquals(i, echo.getA());