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;
}
}
}
}
}
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);
}
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);
}
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);
}
}
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));
}
}
}
Aggregations