Author: clement
Date: Mon Jul 14 11:28:13 2008
New Revision: 676672
URL: http://svn.apache.org/viewvc?rev=676672&view=rev
Log:
Fix issue Felix-632:
Improves immediate component detection in order to avoid to re-set a component
as immediate when it is already immediate.
Fix issue Felix-633:
Uses another thread to create factories and instances. Then once a bundle is
analyzed, the factory and instance creation is delayed and delegate to another
thread.
Fix issue Felix-634:
Catches Throwable when a POJO instance is created in order to catch
"unexpected" errors.
Fix issue Felix-635:
Simplifies factory name computation. Be aware that the factory attribute is no
more supported and is replaced by the public attribute or the name attribute.
The factory name is now computed as following:
if name not null use this, otherwise use the classname.
The factory advertising is now set with the public attribute (true by default).
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
URL:
http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java?rev=676672&r1=676671&r2=676672&view=diff
==============================================================================
---
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
(original)
+++
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
Mon Jul 14 11:28:13 2008
@@ -242,11 +242,8 @@
*/
public String getFactoryName() {
String name = m_componentMetadata.getAttribute("name");
- if (name == null) { // No factory name, try with factory attribute
- name = m_componentMetadata.getAttribute("factory");
- if (name == null || name.equalsIgnoreCase("true") ||
name.equalsIgnoreCase("false")) { // Avoid boolean case
+ if (name == null) { // No factory name, use the classname (mandatory
attribute)
name = m_componentMetadata.getAttribute("classname");
- }
}
return name;
}
@@ -281,7 +278,7 @@
// and does not specified that the component is not immediate.
if (m_componentMetadata.getElements("provides") == null) {
String imm = m_componentMetadata.getAttribute("immediate");
- if (imm == null || !imm.equalsIgnoreCase("false")) {
+ if (imm == null) { // immediate not specified, set the immediate
attribute to true
getLogger().log(
Logger.WARNING,
"The component " + getFactoryName()
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
URL:
http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java?rev=676672&r1=676671&r2=676672&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
(original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
Mon Jul 14 11:28:13 2008
@@ -87,6 +87,11 @@
* List of unbound types.
*/
private final List m_unboundTypes = new ArrayList();
+
+ /**
+ * Thread analyzing arriving bundles and creating iPOJO contributions.
+ */
+ private final CreatorThread m_thread = new CreatorThread();
/**
* Bundle Listener Notification.
@@ -98,9 +103,11 @@
switch (event.getType()) {
case BundleEvent.STARTED:
- startManagementFor(event.getBundle());
+ // Put the bundle in the queue
+ m_thread.addBundle(event.getBundle());
break;
case BundleEvent.STOPPING:
+ m_thread.removeBundle(event.getBundle());
closeManagementFor(event.getBundle());
break;
default:
@@ -115,12 +122,11 @@
*/
private void closeManagementFor(Bundle bundle) {
List toRemove = new ArrayList();
+ // Delete instances declared in the leaving bundle.
+ m_creator.removeInstancesFromBundle(bundle.getBundleId());
for (int k = 0; k < m_factoryTypes.size(); k++) {
ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType)
m_factoryTypes.get(k);
- // Delete instances declared in the leaving bundle.
- m_creator.removeInstancesFromBundle(bundle.getBundleId());
-
// Look for component type created from this bundle.
if (mft.m_created != null) {
List cfs = (List) mft.m_created.remove(bundle);
@@ -249,10 +255,12 @@
m_bundle = context.getBundle();
m_creator = new InstanceCreator(context);
- m_logger = new Logger(m_context, "IPOJO Extender");
+ m_logger = new Logger(m_context, "IPOJO-Extender");
// Begin by initializing core handlers
startManagementFor(m_bundle);
+
+ new Thread(m_thread).start();
synchronized (this) {
// listen to any changes in bundles.
@@ -272,6 +280,7 @@
* @see
org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) {
+ m_thread.stop(); // Stop the thread processing bundles.
m_context.removeBundleListener(this);
for (int k = 0; k < m_factoryTypes.size(); k++) {
@@ -367,7 +376,7 @@
*/
private final class ManagedAbstractFactoryType {
/**
- * TYpe (i.e.) name of the extension.
+ * Type (i.e.) name of the extension.
*/
String m_type;
@@ -501,5 +510,95 @@
m_logger.log(Logger.ERROR, "Cannot find the BundleContext for " +
bundle.getSymbolicName(), null);
return null;
}
+
+
+ /**
+ * The creator thread analyze arriving bundle to create iPOJO contribution.
+ */
+ private class CreatorThread implements Runnable {
+
+ /**
+ * Is the creator thread started?
+ */
+ private boolean m_started = true;
+
+ /**
+ * List of bundle that are going to be analyzed.
+ */
+ private List m_bundles = new ArrayList();
+
+ /**
+ * A bundle is arrived.
+ * This method is synchronized to avoid concurrent modification of the
waiting list.
+ * @param bundle : new bundle
+ */
+ public synchronized void addBundle(Bundle bundle) {
+ m_bundles.add(bundle);
+ notifyAll(); // Notify the thread to force the process.
+ m_logger.log(Logger.INFO, "Creator thread is going to analyze the
bundle " + bundle.getBundleId() + " List : " + m_bundles);
+ }
+
+ /**
+ * A bundle is leaving.
+ * If the bundle was not already processed, the bundle is remove from
the waiting list.
+ * This method is synchronized to avoid concurrent modification of the
waiting list.
+ * @param bundle : the leaving bundle.
+ */
+ public synchronized void removeBundle(Bundle bundle) {
+ m_bundles.remove(bundle);
+ }
+
+ /**
+ * Stop the creator thread.
+ */
+ public synchronized void stop() {
+ m_started = false;
+ m_bundles.clear();
+ notifyAll();
+ }
+
+ /**
+ * Creator thread run method.
+ * While the waiting list is not empty, the thread launch the bundle
analyzing.
+ * When the list is empty, the thread sleeps until the arrival of a
new bundle
+ * or that iPOJO stops.
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ m_logger.log(Logger.INFO, "Creator thread is starting");
+ while (m_started) {
+ Bundle bundle;
+ synchronized (this) {
+ while (m_started && m_bundles.isEmpty()) {
+ try {
+ m_logger.log(Logger.INFO, "Creator thread is
waiting - Nothing to do");
+ wait();
+ } catch (InterruptedException e) {
+ // Interruption, re-check the condition
+ }
+ }
+ if (!m_started) {
+ m_logger.log(Logger.INFO, "Creator thread is
stopping");
+ return; // The thread must be stopped immediately.
+ } else {
+ // The bundle list is not empty, get the bundle.
+ // The bundle object is collected inside the
synchronized block to avoid
+ // concurrent modification. However the real process
is made outside the
+ // mutual exclusion area
+ bundle = (Bundle) m_bundles.remove(0);
+ }
+ }
+ // Process ...
+ m_logger.log(Logger.INFO, "Creator thread is processing " +
bundle.getBundleId());
+ try {
+ startManagementFor(bundle);
+ } catch (Throwable e) {
+ // To be sure to not kill the thread, we catch all
exceptions and errors
+ m_logger.log(Logger.ERROR, "An errors occurs when
analyzing the content or starting the management of " + bundle.getBundleId());
+ }
+ }
+ }
+
+ }
}
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
URL:
http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java?rev=676672&r1=676671&r2=676672&view=diff
==============================================================================
---
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
(original)
+++
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
Mon Jul 14 11:28:13 2008
@@ -127,7 +127,7 @@
m_context = context;
m_componentMetadata = metadata;
m_factoryName = getFactoryName();
- String fac = metadata.getAttribute("factory");
+ String fac = metadata.getAttribute("public");
m_isPublic = fac == null || !fac.equalsIgnoreCase("false");
m_logger = new Logger(m_context, m_factoryName);
m_requiredHandlers = getRequiredHandlerList(); // Call sub-class to
get the list of required handlers.
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
URL:
http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java?rev=676672&r1=676671&r2=676672&view=diff
==============================================================================
---
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
(original)
+++
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
Mon Jul 14 11:28:13 2008
@@ -520,7 +520,7 @@
}
/**
- * Create an instance of the component. This method need to be called one
time only for singleton provided service
+ * Create an instance of the component. This method need to be called one
time only for singleton provided service.
* @return a new instance
*/
public Object createPojoObject() {
@@ -560,6 +560,7 @@
m_factory.getLogger().log(Logger.ERROR,
"[" + m_name + "] createInstance ->
The POJO constructor is not accessible : " + e.getMessage());
stop();
+ return null;
} catch (SecurityException e) {
m_factory.getLogger().log(
Logger.ERROR,
@@ -568,27 +569,28 @@
+ "] createInstance -> The
Component Instance is not accessible (security reason) : "
+ e.getMessage());
stop();
+ return null;
} catch (InvocationTargetException e) {
m_factory.getLogger().log(
Logger.ERROR,
"["
+ m_name
- + "] createInstance ->
Cannot invoke the constructor method (illegal target) : "
+ + "] createInstance ->
Cannot invoke the constructor method - the constructor throws an exception : "
+
e.getTargetException().getMessage());
onError(null, m_className, e.getTargetException());
stop();
+ return null;
} catch (NoSuchMethodException e) {
m_factory.getLogger().log(Logger.ERROR,
"[" + m_name + "] createInstance ->
Cannot invoke the constructor (method not found) : " + e.getMessage());
stop();
- } catch (IllegalArgumentException e) {
- m_factory.getLogger().log(Logger.ERROR,
- "[" + m_name + "] createInstance ->
The POJO constructor invocation failed : " + e.getMessage());
- stop();
- } catch (InstantiationException e) {
+ return null;
+ } catch (Throwable e) {
+ // Catch every other possible error and runtime exception.
m_factory.getLogger().log(Logger.ERROR,
- "[" + m_name + "] createInstance ->
The POJO constructor invocation failed : " + e.getMessage());
+ "[" + m_name + "] createInstance -> The POJO
constructor invocation failed : " + e.getMessage());
stop();
+ return null;
}
} else {
try {
@@ -622,6 +624,7 @@
+ "] createInstance
-> Cannot invoke the factory-method (method not found) : "
+ e2.getMessage());
stop();
+ return null;
}
}
@@ -633,24 +636,13 @@
method.invoke(instance, new Object[] { this });
onExit(null, m_className, instance);
- } catch (SecurityException e) {
- // Error : invocation failed
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "]
createInstance -> Cannot invoke the factory-method : " + e.getMessage());
- stop();
- } catch (IllegalArgumentException e) {
- // Error : arguments mismatch
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "]
createInstance -> Cannot invoke the factory-method : " + e.getMessage());
- stop();
- } catch (IllegalAccessException e) {
- // Error : illegal access
- m_factory.getLogger().log(Logger.ERROR, "[" + m_name + "]
createInstance -> Cannot invoke the factory-method : " + e.getMessage());
- stop();
} catch (InvocationTargetException e) {
// Error : invocation failed
m_factory.getLogger().log(Logger.ERROR,
- "[" + m_name + "] createInstance ->
The factory-method returns an exception : " + e.getTargetException());
+ "[" + m_name + "] createInstance ->
The factory-method throws an exception : " + e.getTargetException());
onError(null, m_className, e.getTargetException());
stop();
+ return null;
} catch (NoSuchMethodException e) {
// Error : _setInstanceManager method is missing
m_factory.getLogger()
@@ -661,11 +653,15 @@
+ "] createInstance -> Cannot invoke the
factory-method (the _setInstanceManager method does not exist) : "
+ e.getMessage());
stop();
+ return null;
+ } catch (Throwable e) {
+ // Catch every other possible error and runtime exception.
+ m_factory.getLogger().log(Logger.ERROR,
+ "[" + m_name + "] createInstance -> The factory-method
invocation failed : " + e.getMessage());
+ stop();
+ return null;
}
-
}
-
-
// Add the new instance in the instance list.
synchronized (this) {
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
URL:
http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java?rev=676672&r1=676671&r2=676672&view=diff
==============================================================================
---
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
(original)
+++
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
Mon Jul 14 11:28:13 2008
@@ -310,8 +310,10 @@
// A NoClassDefFoundError is thrown if the
specification uses a class not accessible by the actual instance.
// It generally comes from a missing import.
throw new IllegalStateException("Cannot create the
Nullable object, a referenced class cannot be loaded: " + e.getMessage());
+ } catch (Throwable e) { // Catch any other exception that
can occurs
+ throw new IllegalStateException("Cannot create the
Nullable object, an unexpected error occurs: " + e.getMessage());
}
- }
+ }
} else {
// Create the default-implementation object.
try {
@@ -323,6 +325,8 @@
throw new IllegalStateException("Cannot load the
default-implementation " + m_di + " : " + e.getMessage());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Cannot load the
default-implementation " + m_di + " : " + e.getMessage());
+ } catch(Throwable e) { // Catch any other exception
+ throw new IllegalStateException("Cannot load the
default-implementation (unexpected exception) " + m_di + " : " +
e.getMessage());
}
}
}