Search in sources :

Example 6 with MethodMetadata

use of org.apache.felix.ipojo.parser.MethodMetadata in project felix by apache.

the class InstanceManager method handleBCInjections.

/**
 * BundleContext injection is not registered with the InstanceManager.
 * We're iterating through factory's all constructors and register first
 * BundleContext parameter as constructor injection. So rest of the code
 * don't have to do anything to handle BundleContext mixed with other
 * injections.
 *
 * @throws ConfigurationException
 */
private void handleBCInjections() throws ConfigurationException {
    MethodMetadata[] constructors = getFactory().getPojoMetadata().getConstructors();
    for (MethodMetadata constructor : constructors) {
        String[] ctorArguments = constructor.getMethodArguments();
        for (int index = 0; index < ctorArguments.length; index++) {
            if (ctorArguments[index].equals(BundleContext.class.getName()) && (m_constructorRegistration == null || !m_constructorRegistration.containsKey(index))) {
                // Check if its used with only other injections.
                boolean injectionsConsistent = true;
                for (int siblingIndex = 0; siblingIndex < ctorArguments.length; siblingIndex++) {
                    if (siblingIndex == index) {
                        continue;
                    }
                    String injectionType = ctorArguments[siblingIndex];
                    if (m_constructorRegistration != null && m_constructorRegistration.containsKey(siblingIndex)) {
                        ConstructorInjector siblingInjector = (ConstructorInjector) m_constructorRegistration.get(siblingIndex);
                        Class injectorClass = siblingInjector.getConstructorParameterType(siblingIndex);
                        if (injectorClass != null && !injectorClass.getName().equals(injectionType)) {
                            injectionsConsistent = false;
                            break;
                        }
                    } else {
                        injectionsConsistent = false;
                        break;
                    }
                }
                if (injectionsConsistent) {
                    Property contextInjection = new Property("__context", null, null, index, null, BundleContext.class.getName(), this, null);
                    contextInjection.setValue(getContext());
                    register(index, contextInjection);
                    // We register the first valid BC injection.
                    break;
                }
            }
        }
    }
}
Also used : MethodMetadata(org.apache.felix.ipojo.parser.MethodMetadata) Property(org.apache.felix.ipojo.util.Property) BundleContext(org.osgi.framework.BundleContext)

Example 7 with MethodMetadata

use of org.apache.felix.ipojo.parser.MethodMetadata in project felix by apache.

the class InstanceManagerTest method testConcurrencyOfMethodId.

@Test
public void testConcurrencyOfMethodId() throws InterruptedException, ConfigurationException, ClassNotFoundException {
    ExecutorService executor = Executors.newFixedThreadPool(CALLERS);
    final AtomicInteger counter = new AtomicInteger();
    final AtomicInteger error = new AtomicInteger();
    ComponentFactory factory = mock(ComponentFactory.class);
    when(factory.loadClass(anyString())).thenReturn(MyComponent.class);
    when(factory.getClassName()).thenReturn(MyComponent.class.getName());
    Bundle bundle = mock(Bundle.class);
    when(bundle.getHeaders()).thenReturn(new Hashtable<String, String>());
    BundleContext context = mock(BundleContext.class);
    when(context.getBundle()).thenReturn(bundle);
    InstanceManager manager = new InstanceManager(factory, context, new HandlerManager[0]);
    Element method1 = new Element("method", "");
    method1.addAttribute(new Attribute("name", "foo"));
    method1.addAttribute(new Attribute("arguments", "{java.lang.String}"));
    method1.addAttribute(new Attribute("names", "{name}"));
    Element method2 = new Element("method", "");
    method2.addAttribute(new Attribute("name", "bar"));
    method2.addAttribute(new Attribute("arguments", "{java.lang.String}"));
    method2.addAttribute(new Attribute("names", "{name}"));
    Element method3 = new Element("method", "");
    method3.addAttribute(new Attribute("name", "baz"));
    method3.addAttribute(new Attribute("arguments", "{java.lang.String}"));
    method3.addAttribute(new Attribute("names", "{name}"));
    final MethodMetadata metadata1 = new MethodMetadata(method1);
    final MethodInterceptor interceptor = new MethodInterceptor() {

        public void onEntry(Object pojo, Member method, Object[] args) {
            if (method != null) {
                counter.getAndIncrement();
            } else {
                System.out.println("No method object for " + args[0]);
                error.incrementAndGet();
            }
        }

        public void onExit(Object pojo, Member method, Object returnedObj) {
            if (method != null) {
                counter.getAndDecrement();
            } else {
                System.out.println("No method object");
                error.incrementAndGet();
            }
        }

        public void onError(Object pojo, Member method, Throwable throwable) {
        }

        public void onFinally(Object pojo, Member method) {
        }
    };
    manager.register(metadata1, interceptor);
    final MethodMetadata metadata2 = new MethodMetadata(method2);
    manager.register(metadata2, interceptor);
    final MethodMetadata metadata3 = new MethodMetadata(method3);
    manager.register(metadata3, interceptor);
    MyComponent component = new MyComponent();
    manager.start();
    manager.load();
    CountDownLatch startSignal = new CountDownLatch(1);
    CountDownLatch doneSignal = new CountDownLatch(CALLERS);
    for (int i = 1; i < CALLERS + 1; ++i) {
        // create and start threads
        executor.execute(new Caller(manager, component, metadata1.getMethodIdentifier(), startSignal, doneSignal, i));
        executor.execute(new Caller(manager, component, metadata2.getMethodIdentifier(), startSignal, doneSignal, i));
        executor.execute(new Caller(manager, component, metadata3.getMethodIdentifier(), startSignal, doneSignal, i));
    }
    // let all threads proceed
    startSignal.countDown();
    assertThat(doneSignal.await(1, TimeUnit.MINUTES)).isTrue();
    assertThat(error.get()).isEqualTo(0);
}
Also used : Attribute(org.apache.felix.ipojo.metadata.Attribute) Bundle(org.osgi.framework.Bundle) Element(org.apache.felix.ipojo.metadata.Element) Matchers.anyString(org.mockito.Matchers.anyString) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecutorService(java.util.concurrent.ExecutorService) MethodMetadata(org.apache.felix.ipojo.parser.MethodMetadata) Member(java.lang.reflect.Member) BundleContext(org.osgi.framework.BundleContext) Test(org.junit.Test)

Example 8 with MethodMetadata

use of org.apache.felix.ipojo.parser.MethodMetadata in project felix by apache.

the class ConfigurationHandler method configure.

/**
 * Configures the handler.
 * Access to field does not require synchronization as this method is executed
 * before any thread access to this object.
 *
 * @param metadata      the metadata of the component
 * @param configuration the instance configuration
 * @throws ConfigurationException one property metadata is not correct
 * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
 */
public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
    // Build the map
    Element[] confs = metadata.getElements("Properties", "");
    Element[] configurables = confs[0].getElements("Property");
    // Check if the component is dynamically configurable
    // Propagation enabled by default.
    m_mustPropagate = true;
    // We must create a copy as the Config Admin dictionary has some limitations
    m_toPropagate = new Hashtable<String, Object>();
    if (configuration != null) {
        Enumeration keys = configuration.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            // we don't propagate properties starting with .
            if (!excluded(key)) {
                m_toPropagate.put(key, configuration.get(key));
            }
        }
    }
    String propa = confs[0].getAttribute("propagation");
    if (propa != null && propa.equalsIgnoreCase("false")) {
        m_mustPropagate = false;
        m_toPropagate = null;
    }
    // Check if the component support ConfigurationADmin reconfiguration
    // Look inside the component type description
    m_managedServicePID = confs[0].getAttribute("pid");
    // Look inside the instance configuration.
    String instanceMSPID = (String) configuration.get(MANAGED_SERVICE_PID);
    if (instanceMSPID != null) {
        m_managedServicePID = instanceMSPID;
    }
    // updated method
    String upd = confs[0].getAttribute("updated");
    if (upd != null) {
        MethodMetadata method = getPojoMetadata().getMethod(upd);
        if (method == null) {
            throw new ConfigurationException("The updated method is not found in the class " + getInstanceManager().getClassName());
        } else if (method.getMethodArguments().length == 0) {
            m_updated = new Callback(upd, new Class[0], false, getInstanceManager());
        } else if (method.getMethodArguments().length == 1 && method.getMethodArguments()[0].equals(Dictionary.class.getName())) {
            m_updated = new Callback(upd, new Class[] { Dictionary.class }, false, getInstanceManager());
        } else {
            throw new ConfigurationException("The updated method is found in the class " + getInstanceManager().getClassName() + " must have either no argument or a Dictionary");
        }
    }
    for (int i = 0; configurables != null && i < configurables.length; i++) {
        String fieldName = configurables[i].getAttribute("field");
        String methodName = configurables[i].getAttribute("method");
        String paramIndex = configurables[i].getAttribute("constructor-parameter");
        int index = -1;
        // The initialize method has fixed the property name.
        String name = configurables[i].getAttribute("name");
        String value = configurables[i].getAttribute("value");
        // The initialize method has fixed the property name.
        String type = configurables[i].getAttribute("type");
        Property prop;
        if (paramIndex == null) {
            prop = new Property(name, fieldName, methodName, value, type, getInstanceManager(), this);
        } else {
            index = Integer.parseInt(paramIndex);
            prop = new Property(name, fieldName, methodName, index, value, type, getInstanceManager(), this);
        }
        addProperty(prop);
        // Check if the instance configuration contains value for the current property :
        if (configuration.get(name) == null) {
            if (fieldName != null && configuration.get(fieldName) != null) {
                prop.setValue(configuration.get(fieldName));
            }
        } else {
            prop.setValue(configuration.get(name));
        }
        if (fieldName != null) {
            FieldMetadata field = new FieldMetadata(fieldName, type);
            getInstanceManager().register(field, prop);
        }
        if (index != -1) {
            getInstanceManager().register(index, prop);
        }
    }
    m_description = new ConfigurationHandlerDescription(this, m_configurableProperties, m_managedServicePID);
}
Also used : FieldMetadata(org.apache.felix.ipojo.parser.FieldMetadata) Element(org.apache.felix.ipojo.metadata.Element) Callback(org.apache.felix.ipojo.util.Callback) MethodMetadata(org.apache.felix.ipojo.parser.MethodMetadata) Property(org.apache.felix.ipojo.util.Property)

Example 9 with MethodMetadata

use of org.apache.felix.ipojo.parser.MethodMetadata in project felix by apache.

the class ConfigurationHandler method initializeComponentFactory.

/**
 * Initialize the component type.
 *
 * @param desc     : component type description to populate.
 * @param metadata : component type metadata.
 * @throws ConfigurationException : metadata are incorrect.
 * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)
 */
public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException {
    Element[] confs = metadata.getElements("Properties", "");
    if (confs == null) {
        return;
    }
    Element[] configurables = confs[0].getElements("Property");
    for (int i = 0; configurables != null && i < configurables.length; i++) {
        String fieldName = configurables[i].getAttribute("field");
        String methodName = configurables[i].getAttribute("method");
        String paramIndex = configurables[i].getAttribute("constructor-parameter");
        if (fieldName == null && methodName == null && paramIndex == null) {
            throw new ConfigurationException("Malformed property : The property needs to contain" + " at least a field, a method or a constructor-parameter");
        }
        String name = configurables[i].getAttribute("name");
        if (name == null) {
            if (fieldName == null && methodName != null) {
                name = methodName;
            } else if (fieldName == null && paramIndex != null) {
                // Extract the name from the arguments.
                MethodMetadata[] constructors = getFactory().getPojoMetadata().getConstructors();
                if (constructors.length != 1) {
                    throw new ConfigurationException("Cannot infer the property name injected in the constructor " + "parameter #" + paramIndex + " - add the `name` attribute");
                } else {
                    int idx = Integer.valueOf(paramIndex);
                    if (constructors[0].getMethodArgumentNames().length > idx) {
                        name = constructors[0].getMethodArgumentNames()[idx];
                    } else {
                        throw new ConfigurationException("Cannot infer the property name injected in the constructor " + "parameter #" + paramIndex + " - not enough argument in the constructor :" + constructors[0].getArguments());
                    }
                }
            } else {
                name = fieldName;
            }
            // Add the type to avoid configure checking
            configurables[i].addAttribute(new Attribute("name", name));
        }
        String value = configurables[i].getAttribute("value");
        // Detect the type of the property
        PojoMetadata manipulation = getFactory().getPojoMetadata();
        String type = null;
        if (methodName != null) {
            MethodMetadata[] method = manipulation.getMethods(methodName);
            if (method.length == 0) {
                type = configurables[i].getAttribute("type");
                if (type == null) {
                    throw new ConfigurationException("Malformed property : The type of the property cannot be discovered, add a 'type' attribute");
                }
            } else {
                if (method[0].getMethodArguments().length != 1) {
                    throw new ConfigurationException("Malformed property :  The method " + methodName + " does not have one argument");
                }
                type = method[0].getMethodArguments()[0];
                // Add the type to avoid configure checking
                configurables[i].addAttribute(new Attribute("type", type));
            }
        } else if (fieldName != null) {
            FieldMetadata field = manipulation.getField(fieldName);
            if (field == null) {
                throw new ConfigurationException("Malformed property : The field " + fieldName + " does not exist in the implementation class");
            }
            type = field.getFieldType();
            // Add the type to avoid configure checking
            configurables[i].addAttribute(new Attribute("type", type));
        } else if (paramIndex != null) {
            int index = Integer.parseInt(paramIndex);
            type = configurables[i].getAttribute("type");
            MethodMetadata[] cts = manipulation.getConstructors();
            // we the index 'index'.
            if (type == null && cts.length > 0 && cts[0].getMethodArguments().length > index) {
                type = cts[0].getMethodArguments()[index];
            } else if (type == null) {
                // Applied only if type was not determined.
                throw new ConfigurationException("Cannot determine the type of the property " + index + ", please use the type attribute");
            }
            configurables[i].addAttribute(new Attribute("type", type));
        }
        // Is the property set to immutable
        boolean immutable = false;
        String imm = configurables[i].getAttribute("immutable");
        immutable = imm != null && imm.equalsIgnoreCase("true");
        boolean mandatory = false;
        String man = configurables[i].getAttribute("mandatory");
        mandatory = man != null && man.equalsIgnoreCase("true");
        PropertyDescription pd;
        if (value == null) {
            // Cannot be immutable if we have no value.
            pd = new PropertyDescription(name, type, null, false);
        } else {
            pd = new PropertyDescription(name, type, value, immutable);
        }
        if (mandatory) {
            pd.setMandatory();
        }
        desc.addProperty(pd);
    }
}
Also used : PropertyDescription(org.apache.felix.ipojo.architecture.PropertyDescription) FieldMetadata(org.apache.felix.ipojo.parser.FieldMetadata) Attribute(org.apache.felix.ipojo.metadata.Attribute) Element(org.apache.felix.ipojo.metadata.Element) PojoMetadata(org.apache.felix.ipojo.parser.PojoMetadata) MethodMetadata(org.apache.felix.ipojo.parser.MethodMetadata)

Example 10 with MethodMetadata

use of org.apache.felix.ipojo.parser.MethodMetadata in project felix by apache.

the class BundleContextHandler method configure.

/**
 * Configures the handler.
 * This method collects all `context` element.
 *
 * @param metadata      the metadata of the component
 * @param configuration the instance configuration
 * @throws org.apache.felix.ipojo.ConfigurationException if the metadata are not correct.
 */
@Override
public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
    Element[] contexts = metadata.getElements("context");
    for (Element element : contexts) {
        BundleContext bc = getBundleContextForConfiguration(element);
        if (element.containsAttribute("constructor-parameter")) {
            String idx = element.getAttribute("constructor-parameter");
            int index = Integer.parseInt(idx);
            final BundleContext injected = bc;
            getLogger().log(Log.DEBUG, "Registering bundle context injection for index " + index + " for instance" + " " + getInstanceManager().getInstanceName());
            getInstanceManager().register(index, new ConstructorInjector() {

                public Object getConstructorParameter(int index) {
                    return injected;
                }

                public Class getConstructorParameterType(int index) {
                    return BundleContext.class;
                }
            });
        } else if (element.containsAttribute("field")) {
            String field = element.getAttribute("field");
            final BundleContext injected = bc;
            FieldMetadata fm = getFactory().getPojoMetadata().getField(field);
            if (fm == null) {
                throw new ConfigurationException("Cannot inject the bundle context in the field " + field + " - " + "reason: the field does not exist in " + getInstanceManager().getClassName());
            }
            if (!BundleContext.class.getName().equals(fm.getFieldType())) {
                throw new ConfigurationException("Cannot inject the bundle context in the field " + field + " - " + "reason: the field " + field + " from " + getInstanceManager().getClassName() + " is not " + "from the BundleContext type");
            }
            getInstanceManager().register(fm, new FieldInterceptor() {

                public void onSet(Object pojo, String fieldName, Object value) {
                // Do nothing.
                }

                public Object onGet(Object pojo, String fieldName, Object value) {
                    return injected;
                }
            });
        } else if (element.containsAttribute("method")) {
            String method = element.getAttribute("method");
            MethodMetadata mm = getFactory().getPojoMetadata().getMethod(method, new String[] { BundleContext.class.getName() });
            if (mm == null) {
                getLogger().log(Log.WARNING, "Cannot find the method " + method + " in the class " + getInstanceManager().getClassName() + ", super classes lookup will be attempted");
            }
            Callback callback = new Callback(method, new Class[] { BundleContext.class }, false, getInstanceManager());
            m_methods.add(new BundleCallback(callback, bc));
        }
    }
}
Also used : FieldMetadata(org.apache.felix.ipojo.parser.FieldMetadata) Element(org.apache.felix.ipojo.metadata.Element) FieldInterceptor(org.apache.felix.ipojo.FieldInterceptor) Callback(org.apache.felix.ipojo.util.Callback) ConfigurationException(org.apache.felix.ipojo.ConfigurationException) ConstructorInjector(org.apache.felix.ipojo.ConstructorInjector) MethodMetadata(org.apache.felix.ipojo.parser.MethodMetadata) BundleContext(org.osgi.framework.BundleContext)

Aggregations

MethodMetadata (org.apache.felix.ipojo.parser.MethodMetadata)13 Element (org.apache.felix.ipojo.metadata.Element)10 ConfigurationException (org.apache.felix.ipojo.ConfigurationException)6 PojoMetadata (org.apache.felix.ipojo.parser.PojoMetadata)6 FieldMetadata (org.apache.felix.ipojo.parser.FieldMetadata)5 Callback (org.apache.felix.ipojo.util.Callback)5 BundleContext (org.osgi.framework.BundleContext)4 PropertyDescription (org.apache.felix.ipojo.architecture.PropertyDescription)2 Attribute (org.apache.felix.ipojo.metadata.Attribute)2 Property (org.apache.felix.ipojo.util.Property)2 Filter (org.osgi.framework.Filter)2 Event (org.osgi.service.event.Event)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Member (java.lang.reflect.Member)1 ArrayList (java.util.ArrayList)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutorService (java.util.concurrent.ExecutorService)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 MBeanException (javax.management.MBeanException)1 ReflectionException (javax.management.ReflectionException)1