blob: 5f0a7069573c66505982eab5009a4bfcfd0dafb4 [file] [log] [blame]
/******************************************************************************
* 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.extensions.annotation;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.easymock.internal.MocksControl;
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
import org.eclipse.gemini.blueprint.service.importer.support.Availability;
import org.eclipse.gemini.blueprint.service.importer.support.ImportContextClassLoaderEnum;
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.util.ReflectionUtils.FieldFilter;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.SortedSet;
/**
* @author Andy Piper
*/
public class OsgiServiceAnnotationTest extends TestCase {
private ServiceReferenceInjectionBeanPostProcessor processor;
private BundleContext context;
protected void setUp() throws Exception {
super.setUp();
processor = new ServiceReferenceInjectionBeanPostProcessor();
context = new MockBundleContext();
processor.setBundleContext(context);
processor.setBeanClassLoader(getClass().getClassLoader());
BeanFactory factory = EasyMock.createMock(BeanFactory.class);
processor.setBeanFactory(factory);
}
/**
* Disabled since it doesn't work as we can't proxy final classes.
*/
public void tstGetServicePropertySetters() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setStringType", new Class<?>[] { String.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
Class<?>[] intfs = (Class[]) getPrivateProperty(pfb, "serviceTypes");
assertEquals(intfs[0], String.class);
setter = AnnotatedBean.class.getMethod("setIntType", new Class<?>[] { Integer.TYPE });
ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
pfb = new OsgiServiceProxyFactoryBean();
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
intfs = (Class[]) getPrivateProperty(pfb, "serviceTypes");
assertEquals(intfs[0], Integer.TYPE);
}
public void testGetServicePropertyCardinality() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithCardinality1_1",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertTrue(pfb.getAvailability() == Availability.MANDATORY);
setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithCardinality0_1",
new Class<?>[] { AnnotatedBean.class });
ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
pfb = new OsgiServiceProxyFactoryBean();
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertFalse(pfb.getAvailability() == Availability.MANDATORY);
}
public void testProperMultiCardinality() throws Exception {
OsgiServiceCollectionProxyFactoryBean pfb = new OsgiServiceCollectionProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithCardinality0_N",
new Class<?>[] { List.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertFalse(pfb.getAvailability() == Availability.MANDATORY);
setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithCardinality1_N",
new Class<?>[] { SortedSet.class });
ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
pfb = new OsgiServiceCollectionProxyFactoryBean();
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertTrue(pfb.getAvailability() == Availability.MANDATORY);
}
public void testErrorMultiCardinality() throws Exception {
OsgiServiceCollectionProxyFactoryBean pfb = new OsgiServiceCollectionProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanErrorTypeWithCardinality1_N",
new Class<?>[] { SortedSet.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
pfb = new OsgiServiceCollectionProxyFactoryBean();
try {
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
fail("IllegalArgumentException should have been thrown");
}
catch (Exception e) {
}
}
public void testGetServicePropertyClassloader() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithClassLoaderClient",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertEquals(pfb.getImportContextClassLoader(), ImportContextClassLoaderEnum.CLIENT);
pfb = new OsgiServiceProxyFactoryBean();
setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithClassLoaderUmanaged",
new Class<?>[] { AnnotatedBean.class });
ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertEquals(pfb.getImportContextClassLoader(), ImportContextClassLoaderEnum.UNMANAGED);
pfb = new OsgiServiceProxyFactoryBean();
setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithClassLoaderServiceProvider",
new Class<?>[] { AnnotatedBean.class });
ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
assertEquals(pfb.getImportContextClassLoader(), ImportContextClassLoaderEnum.SERVICE_PROVIDER);
}
public void testGetServicePropertyBeanName() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithBeanName",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
String beanName = (String) getPrivateProperty(pfb, "serviceBeanName");
;
assertEquals(beanName, "myBean");
}
public void testGetServicePropertyFilter() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithFilter",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
String filter = (String) getPrivateProperty(pfb, "filter");
;
assertEquals(filter, "(wooey=fooo)");
}
public void testGetServicePropertyServiceClass() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeWithServiceType",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
Class<?>[] intfs = (Class[]) getPrivateProperty(pfb, "interfaces");
assertEquals(intfs[0], Object.class);
}
public void testGetServicePropertyComplex() throws Exception {
OsgiServiceProxyFactoryBean pfb = new OsgiServiceProxyFactoryBean();
Method setter = AnnotatedBean.class.getMethod("setAnnotatedBeanTypeComplex",
new Class<?>[] { AnnotatedBean.class });
ServiceReference ref = AnnotationUtils.getAnnotation(setter, ServiceReference.class);
processor.getServiceProperty(pfb, ref, setter.getParameterTypes()[0], null);
Class<?>[] intfs = (Class[]) getPrivateProperty(pfb, "interfaces");
String filter = (String) getPrivateProperty(pfb, "filter");
String beanName = (String) getPrivateProperty(pfb, "serviceBeanName");
assertEquals(intfs[0], AnnotatedBean.class);
assertFalse(pfb.getAvailability() == Availability.MANDATORY);
assertEquals(ImportContextClassLoaderEnum.SERVICE_PROVIDER, pfb.getImportContextClassLoader());
assertEquals(filter, "(id=fooey)");
assertEquals(beanName, "myBean");
}
public void testServiceBeanInjection() throws Exception {
ServiceBean bean = new ServiceBean();
final MyService bean1 = new MyService() {
public Object getId() {
return this;
}
};
final Serializable bean2 = new Serializable() {
public String toString() {
return "bean2";
}
};
BundleContext context = new MockBundleContext() {
public Object getService(org.osgi.framework.ServiceReference reference) {
String clazz = ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
if (clazz == null)
return null;
else if (clazz.equals(MyService.class.getName())) {
return bean1;
}
else if (clazz.equals(Serializable.class.getName())) {
return bean2;
}
return null;
}
};
ServiceReferenceInjectionBeanPostProcessor p = new ServiceReferenceInjectionBeanPostProcessor();
p.setBundleContext(context);
p.setBeanClassLoader(getClass().getClassLoader());
BeanFactory factory = EasyMock.createMock(BeanFactory.class);
MocksControl factoryControl = MocksControl.getControl(factory);
EasyMock.expect(factory.containsBean("&myBean")).andReturn(true);
EasyMock.replay(factory);
p.setBeanFactory(factory);
p.postProcessAfterInitialization(bean, "myBean");
assertSame(bean1.getId(), bean.getServiceBean().getId());
assertSame(bean2.toString(), bean.getSerializableBean().toString());
factoryControl.verify();
}
public void testServiceBeanWithAnnotatedFieldsInjection() throws Exception {
ServiceBeanWithAnnotatedFields bean = new ServiceBeanWithAnnotatedFields();
final MyService bean1 = new MyService() {
public Object getId() {
return this;
}
};
final Serializable bean2 = new Serializable() {
public String toString() {
return "bean2";
}
};
BundleContext context = new MockBundleContext() {
public Object getService(org.osgi.framework.ServiceReference reference) {
String clazz = ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
if (clazz == null)
return null;
else if (clazz.equals(MyService.class.getName())) {
return bean1;
}
else if (clazz.equals(Serializable.class.getName())) {
return bean2;
}
return null;
}
};
ServiceReferenceInjectionBeanPostProcessor p = new ServiceReferenceInjectionBeanPostProcessor();
p.setBundleContext(context);
p.setBeanClassLoader(getClass().getClassLoader());
BeanFactory factory = EasyMock.createMock(BeanFactory.class);
EasyMock.replay(factory);
p.setBeanFactory(factory);
p.postProcessBeforeInitialization(bean, "myBean");
assertSame(bean1.getId(), bean.getServiceBean().getId());
assertSame(bean2.toString(), bean.getSerializableBean().toString());
}
public void testServiceFactoryBeanNotInjected() throws Exception {
ServiceFactoryBean bean = new ServiceFactoryBean();
final MyService bean1 = new MyService() {
public Object getId() {
return this;
}
};
final Serializable bean2 = new Serializable() {
public String toString() {
return "bean2";
}
};
BundleContext context = new MockBundleContext() {
public Object getService(org.osgi.framework.ServiceReference reference) {
String clazz = ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
if (clazz == null)
return null;
else if (clazz.equals(MyService.class.getName())) {
return bean1;
}
else if (clazz.equals(Serializable.class.getName())) {
return bean2;
}
return null;
}
};
ServiceReferenceInjectionBeanPostProcessor p = new ServiceReferenceInjectionBeanPostProcessor();
p.setBundleContext(context);
p.postProcessAfterInitialization(bean, "myBean");
assertNull(bean.getServiceBean());
assertNull(bean.getSerializableBean());
}
public void testServiceFactoryBeanInjected() throws Exception {
ServiceFactoryBean bean = new ServiceFactoryBean();
final MyService bean1 = new MyService() {
public Object getId() {
return this;
}
};
final Serializable bean2 = new Serializable() {
public String toString() {
return "bean2";
}
};
BundleContext context = new MockBundleContext() {
public Object getService(org.osgi.framework.ServiceReference reference) {
String clazz = ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
if (clazz == null)
return null;
else if (clazz.equals(MyService.class.getName())) {
return bean1;
}
else if (clazz.equals(Serializable.class.getName())) {
return bean2;
}
return null;
}
};
ServiceReferenceInjectionBeanPostProcessor p = new ServiceReferenceInjectionBeanPostProcessor();
p.setBundleContext(context);
p.setBeanClassLoader(getClass().getClassLoader());
PropertyValues pvs = p.postProcessPropertyValues(new MutablePropertyValues(), new PropertyDescriptor[] {
new PropertyDescriptor("serviceBean", ServiceFactoryBean.class),
new PropertyDescriptor("serializableBean", ServiceFactoryBean.class) }, bean, "myBean");
MyService msb = (MyService) pvs.getPropertyValue("serviceBean").getValue();
Serializable ssb = (Serializable) pvs.getPropertyValue("serializableBean").getValue();
assertNotNull(msb);
assertNotNull(ssb);
assertSame(bean1.getId(), msb.getId());
assertSame(bean2.toString(), ssb.toString());
}
public void testServiceBeanInjectedValues() throws Exception {
ServiceBean bean = new ServiceBean();
final MyService bean1 = new MyService() {
public Object getId() {
return this;
}
};
final Serializable bean2 = new Serializable() {
public String toString() {
return "bean2";
}
};
BundleContext context = new MockBundleContext() {
public Object getService(org.osgi.framework.ServiceReference reference) {
String clazz = ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
if (clazz == null)
return null;
else if (clazz.equals(MyService.class.getName())) {
return bean1;
}
else if (clazz.equals(Serializable.class.getName())) {
return bean2;
}
return null;
}
};
ServiceReferenceInjectionBeanPostProcessor p = new ServiceReferenceInjectionBeanPostProcessor();
p.setBundleContext(context);
p.setBeanClassLoader(getClass().getClassLoader());
PropertyValues pvs = p.postProcessPropertyValues(new MutablePropertyValues(), new PropertyDescriptor[] {
new PropertyDescriptor("serviceBean", ServiceBean.class),
new PropertyDescriptor("serializableBean", ServiceBean.class) }, bean, "myBean");
MyService msb = (MyService) pvs.getPropertyValue("serviceBean").getValue();
Serializable ssb = (Serializable) pvs.getPropertyValue("serializableBean").getValue();
assertNotNull(msb);
assertNotNull(ssb);
assertSame(bean1.getId(), msb.getId());
assertSame(bean2.toString(), ssb.toString());
}
protected Object getPrivateProperty(final Object target, final String fieldName) {
final Field foundField[] = new Field[1];
ReflectionUtils.doWithFields(target.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
field.setAccessible(true);
foundField[0] = field;
}
}, new FieldFilter() {
public boolean matches(Field field) {
return fieldName.equals(field.getName());
}
});
try {
return foundField[0].get(target);
}
catch (Exception ex) {
// translate
throw new RuntimeException(ex);
}
}
}