/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.service.importer.support;
import java.awt.Polygon;
import java.awt.Shape;
import junit.framework.TestCase;
import org.aopalliance.aop.Advice;
import org.eclipse.gemini.blueprint.TestUtils;
import org.eclipse.gemini.blueprint.service.importer.support.internal.aop.InfrastructureOsgiProxyAdvice;
import org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceDynamicInterceptor;
import org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker;
import org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceStaticInterceptor;
import org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.core.InfrastructureProxy;
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
import org.eclipse.gemini.blueprint.mock.MockServiceReference;
import org.springframework.util.ObjectUtils;
/**
* @author Costin Leau
*
*/
public class OsgiServiceProxyEqualityTest extends TestCase {
private Object target;
private MockBundleContext bundleContext;
private ClassLoader classLoader;
/**
* Simple interface which declares equals.
*
* @author Costin Leau
*
*/
public static interface InterfaceWithEquals {
int getCount();
boolean equals(Object other);
Object doSmth();
}
public static class Implementor implements InterfaceWithEquals {
private int count = 0;
public Implementor(int count) {
this.count = count;
}
public Implementor() {
}
public Object doSmth() {
return ObjectUtils.getIdentityHexString(this);
}
public int getCount() {
return count;
}
public boolean equals(Object other) {
if (this == other)
return true;
if (other instanceof InterfaceWithEquals) {
InterfaceWithEquals oth = (InterfaceWithEquals) other;
return getCount() == oth.getCount();
}
return false;
}
}
private ServiceReference ref;
protected void setUp() throws Exception {
ref = new MockServiceReference();
bundleContext = new MockBundleContext() {
public ServiceReference getServiceReference(String clazz) {
return ref;
}
public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
return new ServiceReference[] { ref };
}
};
classLoader = getClass().getClassLoader();
}
protected void tearDown() throws Exception {
target = null;
bundleContext = null;
}
private Object createProxy(Object target, Class<?> intf, Advice[] advices) {
ProxyFactory factory = new ProxyFactory();
factory.addInterface(intf);
if (advices != null)
for (int i = 0; i < advices.length; i++) {
factory.addAdvice(advices[0]);
}
factory.setTarget(target);
return factory.getProxy();
}
private ServiceDynamicInterceptor createInterceptorWServiceRequired() {
ServiceDynamicInterceptor interceptor = new ServiceDynamicInterceptor(bundleContext, null, null, classLoader);
interceptor.setMandatoryService(true);
interceptor.setProxy(new Object());
interceptor.setServiceImporter(new Object());
interceptor.afterPropertiesSet();
return interceptor;
}
private ServiceDynamicInterceptor createInterceptorWOServiceRequired() {
ServiceDynamicInterceptor interceptor = new ServiceDynamicInterceptor(bundleContext, null, null, classLoader);
interceptor.setMandatoryService(false);
interceptor.setProxy(new Object());
interceptor.setServiceImporter(new Object());
interceptor.afterPropertiesSet();
return interceptor;
}
// TESTS on target W/O an equals defined on it
public void testSameInterceptorEquality() throws Exception {
target = new Polygon();
Advice interceptor = createInterceptorWOServiceRequired();
Object proxyA = createProxy(target, Shape.class, new Advice[] { interceptor });
Object proxyB = createProxy(target, Shape.class, new Advice[] { interceptor });
assertFalse(proxyA == proxyB);
assertEquals(proxyA, proxyB);
}
public void testEqualsInterceptorsEquality() throws Exception {
target = new Polygon();
Advice interceptorA = createInterceptorWOServiceRequired();
Advice interceptorB = createInterceptorWOServiceRequired();
Object proxyA = createProxy(target, Shape.class, new Advice[] { interceptorA });
Object proxyB = createProxy(target, Shape.class, new Advice[] { interceptorB });
assertFalse(proxyA == proxyB);
assertEquals(proxyA, proxyB);
assertEquals(interceptorA, interceptorB);
}
public void testMultipleInterceptorEquality() throws Exception {
target = new Polygon();
Advice interceptorA1 = createInterceptorWOServiceRequired();
Advice interceptorA2 = new LocalBundleContextAdvice(bundleContext);
Advice interceptorA3 = new ServiceTCCLInterceptor(null);
Advice interceptorB1 = createInterceptorWOServiceRequired();
Advice interceptorB2 = new LocalBundleContextAdvice(bundleContext);
Advice interceptorB3 = new ServiceTCCLInterceptor(null);
Object proxyA = createProxy(target, Shape.class, new Advice[] { interceptorA1, interceptorA2, interceptorA3 });
Object proxyB = createProxy(target, Shape.class, new Advice[] { interceptorB1, interceptorB2, interceptorB3 });
assertFalse(proxyA == proxyB);
assertEquals(interceptorA1, interceptorB1);
assertEquals(interceptorA2, interceptorB2);
assertEquals(interceptorA3, interceptorB3);
assertEquals(proxyA, proxyB);
}
//
// TESTS on object with an EQUAL defined on it
//
public void testDifferentInterceptorsButTargetHasEquals() throws Exception {
target = new Implementor();
bundleContext = new MockBundleContext() {
public Object getService(ServiceReference reference) {
return target;
}
};
ServiceDynamicInterceptor interceptorA1 = createInterceptorWServiceRequired();
interceptorA1.setRetryTimeout(10);
Advice interceptorB1 = new ServiceStaticInterceptor(bundleContext, new MockServiceReference());
InterfaceWithEquals proxyA = (InterfaceWithEquals) createProxy(target, InterfaceWithEquals.class,
new Advice[] { interceptorA1 });
InterfaceWithEquals proxyB = (InterfaceWithEquals) createProxy(target, InterfaceWithEquals.class,
new Advice[] { interceptorB1 });
assertFalse(proxyA == proxyB);
assertFalse("interceptors should not be equal", interceptorA1.equals(interceptorB1));
assertEquals(((InterfaceWithEquals) target).doSmth(), proxyA.doSmth());
assertEquals(((InterfaceWithEquals) target).doSmth(), proxyB.doSmth());
assertEquals(proxyA, proxyB);
}
public void testDifferentProxySetupButTargetHasEquals() throws Exception {
target = new Implementor();
Advice interceptorA1 = new LocalBundleContextAdvice(bundleContext);
Advice interceptorB1 = new ServiceTCCLInterceptor(null);
InterfaceWithEquals proxyA = (InterfaceWithEquals) createProxy(target, InterfaceWithEquals.class,
new Advice[] { interceptorA1 });
InterfaceWithEquals proxyB = (InterfaceWithEquals) createProxy(target, InterfaceWithEquals.class,
new Advice[] { interceptorB1 });
assertFalse(proxyA == proxyB);
assertFalse("interceptors should not be equal", interceptorA1.equals(interceptorB1));
assertEquals(((InterfaceWithEquals) target).doSmth(), proxyA.doSmth());
assertEquals(((InterfaceWithEquals) target).doSmth(), proxyB.doSmth());
assertEquals(proxyA, proxyB);
}
public void testSpringInfrastructureProxyOnImportersWithTheSameRef() throws Exception {
Object service = new Object();
ServiceInvoker invokerA = new ServiceStaticInterceptor(createObjectTrackingBundleContext(service), ref);
ServiceInvoker invokerB = new ServiceStaticInterceptor(createObjectTrackingBundleContext(service), ref);
InfrastructureProxy proxyA = new InfrastructureOsgiProxyAdvice(invokerA);
InfrastructureProxy proxyB = new InfrastructureOsgiProxyAdvice(invokerB);
// though this is not normal, we want the interceptors to be different to make sure the wrapped object
// gets properly delegated
assertFalse("invokers should not be equal (they have different bundle contexts)", invokerA.equals(invokerB));
assertFalse("proxies should not be equal", proxyA.equals(proxyB));
assertSame(proxyA.getWrappedObject(), proxyB.getWrappedObject());
}
public void testSpringInfrastructureProxyOnImportersWithDifferentRefs() throws Exception {
Object service = new Object();
BundleContext ctx = createObjectTrackingBundleContext(service);
ServiceInvoker invokerA = new ServiceStaticInterceptor(ctx, new MockServiceReference());
ServiceInvoker invokerB = new ServiceStaticInterceptor(ctx, new MockServiceReference());
InfrastructureProxy proxyA = new InfrastructureOsgiProxyAdvice(invokerA);
InfrastructureProxy proxyB = new InfrastructureOsgiProxyAdvice(invokerB);
assertFalse("invokers should not be equal (they have different service references)", invokerA.equals(invokerB));
assertFalse("proxies should not be equal", proxyA.equals(proxyB));
assertFalse("target objects should not be equal", proxyA.getWrappedObject().equals(proxyB.getWrappedObject()));
}
public void testNakedTargetPropertyReturnedByTheInfrastructureProxy() throws Exception {
Object service = new Object();
ServiceInvoker invoker = new ServiceStaticInterceptor(createObjectTrackingBundleContext(service), ref);
InfrastructureProxy proxy = new InfrastructureOsgiProxyAdvice(invoker);
assertSame(TestUtils.invokeMethod(invoker, "getTarget", null), proxy.getWrappedObject());
assertSame(service, proxy.getWrappedObject());
}
public void testEqualityBetweenInfrastructureProxies() throws Exception {
Advice interceptorA1 = new InfrastructureOsgiProxyAdvice(new ServiceStaticInterceptor(bundleContext, ref));
Advice interceptorB1 = new InfrastructureOsgiProxyAdvice(new ServiceStaticInterceptor(bundleContext, ref));
assertEquals("interceptors should be equal", interceptorA1, interceptorB1);
}
public void testNonEqualityBetweenInfrastructureProxies() throws Exception {
Advice interceptorA1 = new InfrastructureOsgiProxyAdvice(new ServiceStaticInterceptor(bundleContext, ref));
Advice interceptorB1 = new InfrastructureOsgiProxyAdvice(createInterceptorWOServiceRequired());
assertFalse("interceptors should not be equal", interceptorA1.equals(interceptorB1));
}
private BundleContext createObjectTrackingBundleContext(final Object trackedObject) {
return new MockBundleContext() {
public ServiceReference getServiceReference(String clazz) {
return ref;
}
public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
return new ServiceReference[] { ref };
}
public Object getService(ServiceReference reference) {
return (reference.equals(ref) ? trackedObject : super.getService(reference));
}
};
}
}