/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.citrus.springext.util;
import static com.alibaba.citrus.springext.util.SpringExtUtil.*;
import static com.alibaba.citrus.test.TestUtil.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
public class SpringExtUtil_ProxyTests {
private MyProxyTargetFactory factory;
private MyInterfaceImpl actualObject;
private MyInterface proxy;
@Before
public void init() {
actualObject = new MyInterfaceImpl("hello");
factory = new MyProxyTargetFactory(actualObject);
proxy = createProxy(MyInterface.class, factory);
}
@Test
public void noInterface() {
try {
createProxy(null, null);
fail();
} catch (IllegalArgumentException e) {
assertThat(e, exception("no interface"));
}
}
@Test
public void noProxyTargetFactory() {
try {
createProxy(MyInterface.class, null);
fail();
} catch (IllegalArgumentException e) {
assertThat(e, exception("no ProxyTargetFactory"));
}
}
@Test
public void methodNameConflict() {
try {
createProxy(MyInterface2.class, factory);
fail();
} catch (IllegalArgumentException e) {
assertThat(e, exception("Method name conflict: interface ", "$MyInterface2.getObject()"));
}
}
@Test
public void proxyClass() {
Class<?> proxyClass = proxy.getClass();
// 对于同一个interface,总是返回完全相同的class
assertSame(createProxy(MyInterface.class, factory).getClass(), proxyClass);
assertSame(createProxy(MyInterface.class, new MyProxyTargetFactory(actualObject)).getClass(), proxyClass);
assertSame(createProxy(MyInterface.class, new MyProxyTargetFactory(new MyInterfaceImpl("world"))).getClass(),
proxyClass);
// 对于不同的interface,则返回不同的class
assertNotSame(createProxy(List.class, factory).getClass(), proxyClass);
// Class name
assertTrue(proxyClass.getName().startsWith(MyInterface.class.getName()));
}
@Test
public void defaultInterceptor() {
// hashCode
assertTrue(proxy.hashCode() != actualObject.hashCode());
// equals
assertTrue(!proxy.equals(actualObject));
// toString
assertEquals("hello", proxy.toString());
// toString exception
MyInterfaceImpl.toStringException.set(new IllegalArgumentException("wrong!"));
assertEquals("MyInterface[IllegalArgumentException: wrong!]", proxy.toString());
MyInterfaceImpl.toStringException.remove();
// getObject
assertSame(actualObject, ((ProxyTargetFactory) proxy).getObject());
}
@Test
public void proxiedInterceptor() {
assertEquals("hello", proxy.getName());
}
@Test
public void proxyHashCodeAndEquals() {
// same factory
assertHashCodeAndEquals(createProxy(MyInterface.class, factory), true);
// not same but equivalent factory
assertHashCodeAndEquals(createProxy(MyInterface.class, new MyProxyTargetFactory(actualObject)), true);
// not equivalent factory
assertHashCodeAndEquals(createProxy(MyInterface.class, new MyProxyTargetFactory(new MyInterfaceImpl("world"))),
false);
}
private void assertHashCodeAndEquals(Object other, boolean equals) {
if (equals) {
assertEquals(proxy.hashCode(), other.hashCode());
assertEquals(proxy, other);
} else {
assertTrue(proxy.hashCode() != other.hashCode());
assertTrue(!proxy.equals(other));
}
}
@Test
public void assertProxy_() {
// 接受null
assertProxy(null);
// 非proxy
try {
assertProxy(actualObject);
fail();
} catch (IllegalArgumentException e) {
assertThat(e, exception("expects a proxy delegating to a real object, but got an object of type "
+ MyInterfaceImpl.class.getName()));
}
// proxy
assertSame(factory, assertProxy(factory)); // 只要实现了ProxyTargetFactory接口,就认可
assertSame(proxy, assertProxy(proxy));
}
@Test
public void getProxiedObject_() {
// null
assertNull(getProxyTarget(null));
// 非proxy
assertSame(actualObject, getProxyTarget(actualObject));
// proxy
assertSame(actualObject, getProxyTarget(factory)); // 只要实现了ProxyTargetFactory接口,就认可
assertSame(actualObject, getProxyTarget(proxy));
// getObject error
MyProxyTargetFactory.objectException.set(new IllegalArgumentException("wrong!"));
assertNull(getProxyTarget(proxy));
MyProxyTargetFactory.objectException.remove();
}
public static class MyProxyTargetFactory implements ProxyTargetFactory {
private final static ThreadLocal<RuntimeException> objectException = new ThreadLocal<RuntimeException>();
private final Object object;
public MyProxyTargetFactory(Object object) {
this.object = object;
}
public Object getObject() {
if (objectException.get() != null) {
throw objectException.get();
}
return object;
}
@Override
public int hashCode() {
return 31 + (object == null ? 0 : object.hashCode());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MyProxyTargetFactory other = (MyProxyTargetFactory) obj;
if (object == null) {
if (other.object != null) {
return false;
}
} else if (!object.equals(other.object)) {
return false;
}
return true;
}
}
public static interface MyInterface {
String getName();
}
public static class MyInterfaceImpl implements MyInterface {
private final static ThreadLocal<RuntimeException> toStringException = new ThreadLocal<RuntimeException>();
private String name;
public MyInterfaceImpl(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
RuntimeException exception = toStringException.get();
if (exception != null) {
throw exception;
} else {
return name;
}
}
}
public static interface MyInterface2 {
String getObject();
}
}