in ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java [700:896]
protected Object createObject() {
if (m_clazz == null) {
load();
}
// The following code doesn't need to be synchronized as is deal only with immutable fields.
Object instance = null;
if (m_factoryMethod == null) {
// No factory-method, we use the constructor.
try {
// Try to find the correct constructor.
if (m_constructorRegistration != null) {
// Initialize the injected values and types
// We have the IM first.
Object[] values = new Object[m_constructorRegistration.size() + 1];
Class[] types = new Class[m_constructorRegistration.size() + 1];
values[0] = this;
types[0] = InstanceManager.class;
// Iterate over the constructor injector
for (int i = 0; i < m_constructorRegistration.size(); i++) {
ConstructorInjector injector = (ConstructorInjector)
m_constructorRegistration.get(new Integer(i));
Object v = injector.getConstructorParameter(i);
if (v != null) {
values[i + 1] = v;
Class t = injector.getConstructorParameterType(i);
if (t == null) {
t = v.getClass();
}
types[i + 1] = t;
}
}
// Find the constructor.
Constructor cst = m_clazz.getDeclaredConstructor(types);
if (!cst.isAccessible()) {
cst.setAccessible(true);
}
String methodId = MethodMetadata.computeMethodId(cst);
onEntry(null, methodId, values);
instance = cst.newInstance(values);
onExit(instance, methodId, instance);
} else {
// Old semantic
// Try to find if there is a constructor with a bundle context as parameter :
try {
Constructor cst = m_clazz.getDeclaredConstructor(new Class[]{InstanceManager.class, BundleContext.class});
if (!cst.isAccessible()) {
cst.setAccessible(true);
}
Object[] args = new Object[]{this, m_context};
onEntry(null, MethodMetadata.BC_CONSTRUCTOR_ID, new Object[]{m_context});
instance = cst.newInstance(args);
onExit(instance, MethodMetadata.BC_CONSTRUCTOR_ID, instance);
} catch (NoSuchMethodException e) {
// Create an instance if no instance are already created with <init>()BundleContext
if (instance == null) {
Constructor cst = m_clazz.getDeclaredConstructor(new Class[]{InstanceManager.class});
if (!cst.isAccessible()) {
cst.setAccessible(true);
}
Object[] args = new Object[]{this};
onEntry(null, MethodMetadata.EMPTY_CONSTRUCTOR_ID, new Object[0]);
instance = cst.newInstance(args);
onExit(instance, MethodMetadata.EMPTY_CONSTRUCTOR_ID, instance);
}
}
}
} catch (IllegalAccessException e) {
m_logger.log(Logger.ERROR,
"[" + m_name + "] createInstance -> The POJO constructor is not accessible : " + e.getMessage(), e);
stop();
throw new RuntimeException("Cannot create a POJO instance, the POJO constructor is not accessible", e);
} catch (SecurityException e) {
m_logger.log(
Logger.ERROR,
"["
+ m_name
+ "] createInstance -> The POJO constructor is not accessible (security reason) : "
+ e.getMessage(), e
);
stop();
throw new RuntimeException("Cannot create a POJO instance, the POJO constructor is not accessible", e);
} catch (InvocationTargetException e) {
m_logger.log(
Logger.ERROR,
"["
+ m_name
+ "] createInstance -> Cannot invoke the constructor method - the constructor throws an exception : "
+ e.getTargetException().getMessage(), e.getTargetException()
);
onError(null, m_className, e.getTargetException());
stop();
throw new RuntimeException("Cannot create a POJO instance, the POJO constructor has thrown an exception", e.getTargetException());
} catch (NoSuchMethodException e) {
// Improve the log message because of FELIX-4455, we will see if we get better feedback.
m_logger.log(Logger.ERROR,
"[" + m_name + "] iPOJO did not find a suitable constructor to create the " +
"object: " + e.getMessage(), e);
stop();
throw new RuntimeException("Cannot create a POJO instance, the POJO constructor cannot be found", e);
} catch (Throwable e) {
// Catch every other possible error and runtime exception.
m_logger.log(Logger.ERROR,
"[" + m_name + "] createInstance -> The POJO constructor invocation failed : " + e.getMessage(), e);
stop();
throw new RuntimeException("Cannot create a POJO instance, the POJO constructor invocation has thrown an exception", e);
}
} else {
try {
// Build the pojo object with the factory-method.
Method factory = null;
// Try with the bundle context
try {
factory = m_clazz.getDeclaredMethod(m_factoryMethod, new Class[]{BundleContext.class});
if (!factory.isAccessible()) {
factory.setAccessible(true);
}
Object[] args = new Object[]{m_context};
onEntry(null, m_className, args);
instance = factory.invoke(null, new Object[]{m_context});
} catch (NoSuchMethodException e1) {
// Try without the bundle context
try {
factory = m_clazz.getDeclaredMethod(m_factoryMethod, new Class[0]);
if (!factory.isAccessible()) {
factory.setAccessible(true);
}
Object[] args = new Object[0];
onEntry(null, m_className, args);
instance = factory.invoke(null, args);
} catch (NoSuchMethodException e2) {
// Error : factory-method not found
m_logger.log(
Logger.ERROR,
"["
+ m_name
+ "] createInstance -> Cannot invoke the factory-method (method not found) : "
+ e2.getMessage(), e2
);
stop();
throw new RuntimeException("Cannot create a POJO instance, the factory-method cannot be found", e2);
}
}
// Now call the setInstanceManager method.
// Find declaring super class.
Class declaringClass = instance.getClass();
Method method = null;
while (declaringClass != null && method == null) {
try {
method = declaringClass.getDeclaredMethod("_setInstanceManager",
new Class[]{InstanceManager.class});
} catch (NoSuchMethodException e) {
//Do nothing
}
declaringClass = declaringClass.getSuperclass();
}
if (method == null) {
// Error : _setInstanceManager method is missing
m_logger
.log(
Logger.ERROR,
"["
+ m_name
+ "] createInstance -> Cannot invoke the factory-method (the _setInstanceManager method does not exist"
);
stop();
throw new RuntimeException("Cannot create a POJO instance, the factory-method cannot be found");
}
if (!method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(instance, new Object[]{this});
onExit(null, m_className, instance);
} catch (InvocationTargetException e) {
// Error : invocation failed
m_logger.log(Logger.ERROR,
"[" + m_name + "] createInstance -> The factory-method throws an exception : " + e.getTargetException(), e.getTargetException());
onError(null, m_className, e.getTargetException());
stop();
throw new RuntimeException("Cannot create a POJO instance, the factory-method has thrown an exception", e.getTargetException());
} catch (Throwable e) {
// Catch every other possible error and runtime exception.
m_logger.log(Logger.ERROR,
"[" + m_name + "] createInstance -> The factory-method invocation failed : " + e.getMessage(), e);
stop();
throw new RuntimeException("Cannot create a POJO instance, the factory-method invocation has thrown an exception", e);
}
}
return instance;
}