/*
* Copyright 2002-2005 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.support;
import java.io.Serializable;
import junit.framework.TestCase;
import org.aopalliance.intercept.MethodInterceptor;
import org.easymock.MockControl;
import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.TimeStamped;
import org.springframework.aop.interceptor.SerializableNopInterceptor;
import org.springframework.beans.INestedTestBean;
import org.springframework.beans.ITestBean;
import org.springframework.beans.NestedTestBean;
import org.springframework.beans.Person;
import org.springframework.beans.SerializablePerson;
import org.springframework.beans.TestBean;
import org.springframework.util.SerializationTestUtils;
/**
* @author Rod Johnson
* @since 13.05.2003
*/
public class DelegatingIntroductionInterceptorTests extends TestCase {
public void testNullTarget() throws Exception {
try {
IntroductionInterceptor ii = new DelegatingIntroductionInterceptor(null);
fail("Shouldn't accept null target");
}
catch (IllegalArgumentException ex) {
// OK
}
}
public void testIntroductionInterceptorWithDelegation() throws Exception {
TestBean raw = new TestBean();
assertTrue(! (raw instanceof TimeStamped));
ProxyFactory factory = new ProxyFactory(raw);
MockControl tsControl = MockControl.createControl(TimeStamped.class);
TimeStamped ts = (TimeStamped) tsControl.getMock();
ts.getTimeStamp();
long timestamp = 111L;
tsControl.setReturnValue(timestamp, 1);
tsControl.replay();
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
TimeStamped tsp = (TimeStamped) factory.getProxy();
assertTrue(tsp.getTimeStamp() == timestamp);
tsControl.verify();
}
public void testIntroductionInterceptorWithInterfaceHierarchy() throws Exception {
TestBean raw = new TestBean();
assertTrue(! (raw instanceof SubTimeStamped));
ProxyFactory factory = new ProxyFactory(raw);
MockControl tsControl = MockControl.createControl(SubTimeStamped.class);
SubTimeStamped ts = (SubTimeStamped) tsControl.getMock();
ts.getTimeStamp();
long timestamp = 111L;
tsControl.setReturnValue(timestamp, 1);
tsControl.replay();
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), SubTimeStamped.class));
SubTimeStamped tsp = (SubTimeStamped) factory.getProxy();
assertTrue(tsp.getTimeStamp() == timestamp);
tsControl.verify();
}
public void testIntroductionInterceptorWithSuperInterface() throws Exception {
TestBean raw = new TestBean();
assertTrue(! (raw instanceof TimeStamped));
ProxyFactory factory = new ProxyFactory(raw);
MockControl tsControl = MockControl.createControl(SubTimeStamped.class);
SubTimeStamped ts = (SubTimeStamped) tsControl.getMock();
ts.getTimeStamp();
long timestamp = 111L;
tsControl.setReturnValue(timestamp, 1);
tsControl.replay();
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), TimeStamped.class));
TimeStamped tsp = (TimeStamped) factory.getProxy();
assertTrue(!(tsp instanceof SubTimeStamped));
assertTrue(tsp.getTimeStamp() == timestamp);
tsControl.verify();
}
public void testAutomaticInterfaceRecognitionInDelegate() throws Exception {
final long t = 1001L;
class Test implements TimeStamped, ITest {
public void foo() throws Exception {
}
public long getTimeStamp() {
return t;
}
}
DelegatingIntroductionInterceptor ii = new DelegatingIntroductionInterceptor(new Test());
TestBean target = new TestBean();
ProxyFactory pf = new ProxyFactory(target);
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
//assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
TimeStamped ts = (TimeStamped) pf.getProxy();
assertTrue(ts.getTimeStamp() == t);
((ITest) ts).foo();
((ITestBean) ts).getAge();
}
public void testAutomaticInterfaceRecognitionInSubclass() throws Exception {
final long t = 1001L;
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped, ITest {
public void foo() throws Exception {
}
public long getTimeStamp() {
return t;
}
}
DelegatingIntroductionInterceptor ii = new TestII();
TestBean target = new TestBean();
ProxyFactory pf = new ProxyFactory(target);
IntroductionAdvisor ia = new DefaultIntroductionAdvisor(ii);
assertTrue(ia.isPerInstance());
pf.addAdvisor(0, ia);
//assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
TimeStamped ts = (TimeStamped) pf.getProxy();
assertTrue(ts instanceof TimeStamped);
// Shoulnd't proxy framework interfaces
assertTrue(!(ts instanceof MethodInterceptor));
assertTrue(!(ts instanceof IntroductionInterceptor));
assertTrue(ts.getTimeStamp() == t);
((ITest) ts).foo();
((ITestBean) ts).getAge();
// Test removal
ii.suppressInterface(TimeStamped.class);
// Note that we need to construct a new proxy factory,
// or suppress the interface on the proxy factory
pf = new ProxyFactory(target);
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
Object o = pf.getProxy();
assertTrue(!(o instanceof TimeStamped));
}
public void testIntroductionInterceptorDoesntReplaceToString() throws Exception {
TestBean raw = new TestBean();
assertTrue(! (raw instanceof TimeStamped));
ProxyFactory factory = new ProxyFactory(raw);
TimeStamped ts = new SerializableTimeStamped(0);
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts) {
public String toString() {
throw new UnsupportedOperationException("Shouldn't be invoked");
}
}));
TimeStamped tsp = (TimeStamped) factory.getProxy();
assertEquals(0, tsp.getTimeStamp());
assertEquals(raw.toString(), tsp.toString());
}
public void testDelegateReturnsThisIsMassagedToReturnProxy() {
NestedTestBean target = new NestedTestBean();
String company = "Interface21";
target.setCompany(company);
TestBean delegate = new TestBean() {
public ITestBean getSpouse() {
return this;
}
};
ProxyFactory pf = new ProxyFactory(target);
pf.addAdvice(new DelegatingIntroductionInterceptor(delegate));
INestedTestBean proxy = (INestedTestBean) pf.getProxy();
assertEquals(company, proxy.getCompany());
ITestBean introduction = (ITestBean) proxy;
assertSame("Introduced method returning delegate returns proxy", introduction, introduction.getSpouse());
assertTrue("Introduced method returning delegate returns proxy", AopUtils.isAopProxy(introduction.getSpouse()));
}
public void testSerializableDelegatingIntroductionInterceptorSerializable() throws Exception {
SerializablePerson serializableTarget = new SerializablePerson();
String name = "Tony";
serializableTarget.setName("Tony");
ProxyFactory factory = new ProxyFactory(serializableTarget);
factory.addInterface(Person.class);
long time = 1000;
TimeStamped ts = new SerializableTimeStamped(time);
factory.addAdvisor(new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
factory.addAdvice(new SerializableNopInterceptor());
Person p = (Person) factory.getProxy();
assertEquals(name, p.getName());
assertEquals(time, ((TimeStamped) p).getTimeStamp());
Person p1 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
assertEquals(name, p1.getName());
assertEquals(time, ((TimeStamped) p1).getTimeStamp());
}
// public void testDelegatingIntroductionInterceptorDoesntMakeNonserializableSerializable() throws Exception {
// // Target is NOT serialiable
// TestBean raw = new TestBean();
// ProxyFactory factory = new ProxyFactory(raw);
// factory.addInterface(Person.class);
// long time = 1000;
// TimeStamped ts = new SerializableTimeStamped(time);
//
// factory.addAdvisor(new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
// Object proxy = factory.getProxy();
//
// assertFalse(proxy instanceof Serializable);
// }
// Test when target implements the interface: should get interceptor by preference.
public void testIntroductionMasksTargetImplementation() throws Exception {
final long t = 1001L;
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped {
public long getTimeStamp() {
return t;
}
}
DelegatingIntroductionInterceptor ii = new TestII();
// != t
TestBean target = new TargetClass(t + 1);
ProxyFactory pf = new ProxyFactory(target);
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
TimeStamped ts = (TimeStamped) pf.getProxy();
// From introduction interceptor, not target
assertTrue(ts.getTimeStamp() == t);
}
private static class SerializableTimeStamped implements TimeStamped, Serializable {
private final long ts;
public SerializableTimeStamped(long ts) {
this.ts = ts;
}
public long getTimeStamp() {
return ts;
}
}
public static class TargetClass extends TestBean implements TimeStamped {
long t;
public TargetClass(long t) {
this.t = t;
}
public long getTimeStamp() {
return t;
}
}
public interface ITest {
void foo() throws Exception;
}
private static interface SubTimeStamped extends TimeStamped {
}
}