cucumber.java.runtime.osgi.OsgiObjectFactory Maven / Gradle / Ivy
package cucumber.java.runtime.osgi;
import java.lang.reflect.Field;
import java.util.Collection;
import javax.inject.Inject;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import cucumber.api.osgi.Filter;
import cucumber.api.osgi.ServiceNotFoundException;
import cucumber.api.osgi.TimeoutException;
public class OsgiObjectFactory extends OsgiObjectFactoryBase {
private BundleContext bundleContext;
public OsgiObjectFactory(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
protected void prepareGlueInstance(Object instance) {
injectFields(instance);
}
public void injectFields(Object target) {
for ( Class> targetClass = target.getClass();
targetClass != Object.class;
targetClass = targetClass.getSuperclass()) {
injectDeclaredFields(target, targetClass);
}
}
private void injectDeclaredFields(Object target, Class> targetClass) {
for (Field field : targetClass.getDeclaredFields()) {
if (field.getAnnotation(Inject.class) != null) {
injectField(target, targetClass, field);
}
}
}
private void injectField(Object target, Class> targetClass, Field field) {
Class> type = field.getType();
long timeout = 500;
String filterString = "";
final Filter filter = field.getAnnotation(Filter.class);
if (filter != null) {
filterString = filter.value();
if (filter.timeout() != 0)
timeout = filter.timeout();
}
// Retrieve bundle Context just before calling getService to avoid that the bundle restarts
// in between
final Object service = (BundleContext.class == type) ?
bundleContext : getService(type, timeout, filterString);
setField(target, field, service);
}
private void setField(Object target, Field field, Object service) {
try {
final boolean accessible = field.isAccessible();
if (!accessible) field.setAccessible(true);
try {
field.set(target, service);
}
finally {
if (!accessible) field.setAccessible(false);
}
}
catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
private Object getService(Class> type, long timeout, String filter) {
final String serviceName = type.getName() + " " + filter;
try {
final long tryUntil = System.currentTimeMillis() + timeout;
Object service = null;
search : while (service == null) {
final Collection> serviceReferences = bundleContext.getServiceReferences(type, filter.isEmpty() ? null : filter);
for (Object serviceReference : serviceReferences) {
service = bundleContext.getService((ServiceReference>) serviceReference);
break search;
}
if (tryUntil < System.currentTimeMillis())
break;
Thread.sleep(20);
}
if (service == null)
throw new ServiceNotFoundException(serviceName);
return service;
} catch (InvalidSyntaxException e) {
throw new IllegalArgumentException(e);
} catch (InterruptedException e) {
throw new TimeoutException(serviceName);
}
}
}