1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.aop.framework;
18 
19 import static org.easymock.EasyMock.createMock;
20 import static org.easymock.EasyMock.expect;
21 import static org.easymock.EasyMock.replay;
22 import static org.easymock.EasyMock.verify;
23 import static org.junit.Assert.*;
24 
25 import java.io.Serializable;
26 
27 import org.aopalliance.intercept.MethodInterceptor;
28 import org.aopalliance.intercept.MethodInvocation;
29 
30 import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
31 import org.springframework.aop.support.AopUtils;
32 import org.springframework.beans.IOther;
33 import org.springframework.beans.ITestBean;
34 import org.springframework.beans.TestBean;
35 
36 /**
37  * @since 13.03.2003
38  * @author Rod Johnson
39  * @author Juergen Hoeller
40  * @author Chris Beams
41  */
42 @SuppressWarnings("serial")
43 public final class JdkDynamicProxyTests extends AbstractAopProxyTests implements Serializable {
44 
createProxy(ProxyCreatorSupport as)45 	protected Object createProxy(ProxyCreatorSupport as) {
46 		assertFalse("Not forcible CGLIB", as.isProxyTargetClass());
47 		Object proxy = as.createAopProxy().getProxy();
48 		assertTrue("Should be a JDK proxy: " + proxy.getClass(), AopUtils.isJdkDynamicProxy(proxy));
49 		return proxy;
50 	}
51 
createAopProxy(AdvisedSupport as)52 	protected AopProxy createAopProxy(AdvisedSupport as) {
53 		return new JdkDynamicAopProxy(as);
54 	}
55 
testNullConfig()56 	public void testNullConfig() {
57 		try {
58 			new JdkDynamicAopProxy(null);
59 			fail("Shouldn't allow null interceptors");
60 		}
61 		catch (IllegalArgumentException ex) {
62 			// Ok
63 		}
64 	}
65 
testProxyIsJustInterface()66 	public void testProxyIsJustInterface() throws Throwable {
67 		TestBean raw = new TestBean();
68 		raw.setAge(32);
69 		AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
70 		pc.setTarget(raw);
71 		JdkDynamicAopProxy aop = new JdkDynamicAopProxy(pc);
72 
73 		Object proxy = aop.getProxy();
74 		assertTrue(proxy instanceof ITestBean);
75 		assertTrue(!(proxy instanceof TestBean));
76 	}
77 
testInterceptorIsInvokedWithNoTarget()78 	public void testInterceptorIsInvokedWithNoTarget() throws Throwable {
79 		// Test return value
80 		int age = 25;
81 		MethodInterceptor mi = createMock(MethodInterceptor.class);
82 
83 		AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class });
84 		pc.addAdvice(mi);
85 		AopProxy aop = createAopProxy(pc);
86 
87 		expect(mi.invoke(null)).andReturn(age);
88 		replay(mi);
89 
90 		ITestBean tb = (ITestBean) aop.getProxy();
91 		assertTrue("correct return value", tb.getAge() == age);
92 		verify(mi);
93 	}
94 
testTargetCanGetInvocationWithPrivateClass()95 	public void testTargetCanGetInvocationWithPrivateClass() throws Throwable {
96 		final ExposedInvocationTestBean expectedTarget = new ExposedInvocationTestBean() {
97 			protected void assertions(MethodInvocation invocation) {
98 				assertTrue(invocation.getThis() == this);
99 				assertTrue("Invocation should be on ITestBean: " + invocation.getMethod(),
100 					invocation.getMethod().getDeclaringClass() == ITestBean.class);
101 			}
102 		};
103 
104 		AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class, IOther.class });
105 		pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
106 		TrapTargetInterceptor tii = new TrapTargetInterceptor() {
107 			public Object invoke(MethodInvocation invocation) throws Throwable {
108 				// Assert that target matches BEFORE invocation returns
109 				assertEquals("Target is correct", expectedTarget, invocation.getThis());
110 				return super.invoke(invocation);
111 			}
112 		};
113 		pc.addAdvice(tii);
114 		pc.setTarget(expectedTarget);
115 		AopProxy aop = createAopProxy(pc);
116 
117 		ITestBean tb = (ITestBean) aop.getProxy();
118 		tb.getName();
119 		// Not safe to trap invocation
120 		//assertTrue(tii.invocation == target.invocation);
121 
122 		//assertTrue(target.invocation.getProxy() == tb);
123 
124 		//	((IOther) tb).absquatulate();
125 		//MethodInvocation minv =  tii.invocation;
126 		//assertTrue("invoked on iother, not " + minv.getMethod().getDeclaringClass(), minv.getMethod().getDeclaringClass() == IOther.class);
127 		//assertTrue(target.invocation == tii.invocation);
128 	}
129 
testProxyNotWrappedIfIncompatible()130 	public void testProxyNotWrappedIfIncompatible() {
131 		FooBar bean = new FooBar();
132 		ProxyCreatorSupport as = new ProxyCreatorSupport();
133 		as.setInterfaces(new Class[] {Foo.class});
134 		as.setTarget(bean);
135 
136 		Foo proxy = (Foo) createProxy(as);
137 		assertSame("Target should be returned when return types are incompatible", bean, proxy.getBarThis());
138 		assertSame("Proxy should be returned when return types are compatible", proxy, proxy.getFooThis());
139 
140 	}
141 
testEqualsAndHashCodeDefined()142 	public void testEqualsAndHashCodeDefined() throws Exception {
143 		AdvisedSupport as = new AdvisedSupport(new Class[]{Named.class});
144 		as.setTarget(new Person());
145 		JdkDynamicAopProxy aopProxy = new JdkDynamicAopProxy(as);
146 		Named proxy = (Named) aopProxy.getProxy();
147 		Named named = new Person();
148 		assertEquals("equals() returned false", proxy, named);
149 		assertEquals("hashCode() not equal", proxy.hashCode(), named.hashCode());
150 	}
151 
152 
153 	public static interface Foo {
154 
getBarThis()155 		Bar getBarThis();
156 
getFooThis()157 		Foo getFooThis();
158 	}
159 
160 
161 	public static interface Bar {
162 
163 	}
164 
165 
166 	public static class FooBar implements Foo, Bar {
167 
getBarThis()168 		public Bar getBarThis() {
169 			return this;
170 		}
171 
getFooThis()172 		public Foo getFooThis() {
173 			return this;
174 		}
175 	}
176 
177 
178 	public static interface Named {
179 
getName()180 		String getName();
181 
equals(Object other)182 		boolean equals(Object other);
183 
hashCode()184 		int hashCode();
185 	}
186 
187 
188 	public static class Person implements Named {
189 
190 		private final String name = "Rob Harrop";
191 
getName()192 		public String getName() {
193 			return this.name;
194 		}
195 
equals(Object o)196 		public boolean equals(Object o) {
197 			if (this == o) return true;
198 			if (o == null || getClass() != o.getClass()) return false;
199 
200 			final Person person = (Person) o;
201 
202 			if (!name.equals(person.name)) return false;
203 
204 			return true;
205 		}
206 
hashCode()207 		public int hashCode() {
208 			return name.hashCode();
209 		}
210 	}
211 
212 }
213