blob: 13926595bc381fe1df51687ceff77ceabf184a43 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 WARRANTIESOR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.proxy.itests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import org.apache.aries.itest.AbstractIntegrationTest;
import org.apache.aries.proxy.InvocationListener;
import org.apache.aries.proxy.ProxyManager;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
public class AbstractProxyTest extends AbstractIntegrationTest {
public final static class TestCallable implements Callable<Object> {
private Object list = new ArrayList<Object>();
public Object call() throws Exception {
return list;
}
public void setReturn(Object o) {
list = o;
}
}
public static class TestDelegate extends AbstractList<String> implements Callable<String> {
private final String message;
public TestDelegate(String message) {
super();
this.message = message;
}
public String call() throws Exception {
return message;
}
public boolean equals(Object o) {
if(o instanceof TestDelegate){
return message.equals(((TestDelegate)o).message);
}
return false;
}
public void throwException() {
throw new RuntimeException();
}
public void testInternallyCaughtException() {
try {
throw new RuntimeException();
} catch (RuntimeException re) {
// no op
}
}
@Override
public String get(int location) {
return null;
}
@Override
public int size() {
return 0;
}
}
private class TestListener implements InvocationListener {
boolean preInvoke = false;
boolean postInvoke = false;
boolean postInvokeExceptionalReturn = false;
Object token;
public Object preInvoke(Object proxy, Method m, Object[] args)
throws Throwable {
preInvoke = true;
token = new Object();
return token;
}
public void postInvoke(Object token, Object proxy, Method m,
Object returnValue) throws Throwable {
postInvoke = this.token == token;
}
public void postInvokeExceptionalReturn(Object token, Object proxy,
Method m, Throwable exception) throws Throwable {
postInvokeExceptionalReturn = this.token == token;
}
public void clear() {
preInvoke = false;
postInvoke = false;
postInvokeExceptionalReturn = false;
token = null;
}
}
@SuppressWarnings("unchecked")
@Test
public void testEquals() throws Exception {
ProxyManager mgr = context().getService(ProxyManager.class);
Bundle b = FrameworkUtil.getBundle(this.getClass());
TestCallable c = new TestCallable();
c.setReturn(new TestDelegate("One"));
TestCallable c2 = new TestCallable();
c.setReturn(new TestDelegate("Two"));
Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(List.class);
Object proxy = mgr.createDelegatingProxy(b, classes, c, new TestDelegate("Three"));
Object otherProxy = mgr.createDelegatingProxy(b, classes, c, new TestDelegate("Four"));
Object totallyOtherProxy = mgr.createDelegatingProxy(b, classes, c2, new TestDelegate("Five"));
assertTrue("The object is not equal to itself", proxy.equals(proxy));
assertTrue("The object is not equal to another proxy of itself", proxy.equals(otherProxy));
assertFalse("The object is equal to proxy to another object", proxy.equals(totallyOtherProxy));
}
@Test
public void testDelegation() throws Exception {
ProxyManager mgr = context().getService(ProxyManager.class);
Bundle b = FrameworkUtil.getBundle(this.getClass());
TestCallable c = new TestCallable();
Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(TestDelegate.class);
TestDelegate proxy = (TestDelegate) mgr.createDelegatingProxy(b, classes, c, new TestDelegate(""));
c.setReturn(new TestDelegate("Hello"));
assertEquals("Wrong message", "Hello", proxy.call());
c.setReturn(new TestDelegate("Hello again"));
assertEquals("Wrong message", "Hello again", proxy.call());
}
@Test
public void testInterception() throws Exception {
ProxyManager mgr = context().getService(ProxyManager.class);
Bundle b = FrameworkUtil.getBundle(this.getClass());
TestDelegate td = new TestDelegate("Hello");
Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(TestDelegate.class);
TestListener tl = new TestListener();
TestDelegate proxy = (TestDelegate) mgr.createInterceptingProxy(b, classes, td, tl);
//We need to call clear here, because the object will have had its toString() called
tl.clear();
assertCalled(tl, false, false, false);
assertEquals("Wrong message", "Hello", proxy.call());
assertCalled(tl, true, true, false);
tl.clear();
assertCalled(tl, false, false, false);
try {
proxy.throwException();
fail("Should throw an exception");
} catch (RuntimeException re) {
assertCalled(tl, true, false, true);
}
tl.clear();
assertCalled(tl, false, false, false);
try {
proxy.testInternallyCaughtException();
} finally {
assertCalled(tl, true, true, false);
}
}
@Test
public void testDelegationAndInterception() throws Exception {
ProxyManager mgr = context().getService(ProxyManager.class);
Bundle b = FrameworkUtil.getBundle(this.getClass());
TestCallable c = new TestCallable();
Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(TestDelegate.class);
TestListener tl = new TestListener();
TestDelegate proxy = (TestDelegate) mgr.createDelegatingInterceptingProxy(b, classes, c, new TestDelegate(""), tl);
c.setReturn(new TestDelegate("Hello"));
//We need to call clear here, because the object will have had its toString() called
tl.clear();
assertCalled(tl, false, false, false);
assertEquals("Wrong message", "Hello", proxy.call());
assertCalled(tl, true, true, false);
tl.clear();
assertCalled(tl, false, false, false);
c.setReturn(new TestDelegate("Hello again"));
assertEquals("Wrong message", "Hello again", proxy.call());
assertCalled(tl, true, true, false);
tl.clear();
assertCalled(tl, false, false, false);
try {
proxy.throwException();
fail("Should throw an exception");
} catch (RuntimeException re) {
assertCalled(tl, true, false, true);
}
tl.clear();
assertCalled(tl, false, false, false);
try {
proxy.testInternallyCaughtException();
} finally {
assertCalled(tl, true, true, false);
}
}
private void assertCalled(TestListener listener, boolean pre, boolean post, boolean ex) {
assertEquals(pre, listener.preInvoke);
assertEquals(post, listener.postInvoke);
assertEquals(ex, listener.postInvokeExceptionalReturn);
}
}