All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.java.runtime.osgi.OsgiObjectFactory Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show newest version
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);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy