Fix the issue FELIX-558 by catching the NoClassDefFound error and providing an explanation message.
The error is also logged.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@656694 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 82a242a..dcb7271 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -46,20 +46,22 @@
     /**
      * Reference on the Dependency Handler.
      */
-    private DependencyHandler m_handler;
+    private final DependencyHandler m_handler;
 
     /**
      * Field of the dependency.
      */
-    private String m_field;
+    private final String m_field;
 
     /**
      * List of dependency callback.
+     * Immutable once set.
      */
     private DependencyCallback[] m_callbacks;
 
     /**
      * Is the dependency a service level dependency.
+     * Immutable once set.
      */
     private boolean m_isServiceLevelRequirement;
 
@@ -76,25 +78,27 @@
     /**
      * Thread Local.
      */
-    private ServiceUsage m_usage;
+    private final ServiceUsage m_usage;
 
     /**
      * Nullable object.
+     * Immutable once set.
      */
     private Object m_nullable;
 
     /**
      * Default-Implementation.
      */
-    private String m_di;
+    private final String m_di;
     
     /**
      * Is the Nullable pattern enable?
      */
-    private boolean m_supportNullable;
+    private final boolean m_supportNullable;
 
     /**
      * Id of the dependency.
+     * Immutable once set.
      */
     private String m_id;
 
@@ -117,9 +121,11 @@
     public Dependency(DependencyHandler handler, String field, Class spec, Filter filter, boolean isOptional, boolean isAggregate, boolean nullable, String identity, BundleContext context, int policy, Comparator cmp, String defaultImplem) {
         super(spec, isAggregate, isOptional, filter, cmp, policy, context, handler);
         m_handler = handler;
+        m_field = field;
         if (field != null) {
-            m_field = field;
             m_usage = new ServiceUsage();
+        } else {
+            m_usage = null;
         }
         
         m_supportNullable = nullable;
@@ -138,7 +144,8 @@
     /**
      * Set the specification of the current dependency.
      * In order to store the id of the dependency, this
-     * method is override.
+     * method is override. This method is called during the 
+     * configuration.
      * @param spec : request service Class
      * @see org.apache.felix.ipojo.util.DependencyModel#setSpecification(java.lang.Class)
      */
@@ -155,6 +162,7 @@
 
     /**
      * Add a callback to the dependency.
+     * This method is called during the configuration.
      * @param callback : callback to add
      */
     protected void addDependencyCallback(DependencyCallback callback) {
@@ -172,7 +180,7 @@
      * Stop the current dependency.
      * @see org.apache.felix.ipojo.util.DependencyModel#stop()
      */
-    public void stop() {
+    public synchronized void stop() {
         m_isStarted = false;
         super.stop();
     }
@@ -197,30 +205,32 @@
      * Call the bind method.
      * @param pojo : pojo instance on which calling the bind method.
      */
-    protected synchronized void onObjectCreation(Object pojo) {
-        if (!m_isStarted) { return; }
+    protected void onObjectCreation(Object pojo) {
+        ServiceReference[] refs;
+        synchronized (this) {
+            if (!m_isStarted) { return; }
 
-        // We are notified of an instance creation, we have to freeze when the static policy is used
-        if (getBindingPolicy() == STATIC_BINDING_POLICY) {
-            m_isFrozen = true;
+            // We are notified of an instance creation, we have to freeze when the static policy is used
+            if (getBindingPolicy() == STATIC_BINDING_POLICY) {
+                m_isFrozen = true;
+            }
+
+            // Check optional case : nullable object case : do not call bind on nullable object
+            if (isOptional() && getSize() == 0) { return; }
+            
+            refs = getServiceReferences(); // Stack confinement.
         }
 
-        // Check optional case : nullable object case : do not call bind on nullable object
-        if (isOptional() && getSize() == 0) { return; }
-
         // Call bind callback.
-        for (int j = 0; m_callbacks != null && j < m_callbacks.length; j++) {
+        for (int j = 0; m_callbacks != null && j < m_callbacks.length; j++) { // The array is constant.
             if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
                 if (isAggregate()) {
-                    ServiceReference[] refs = getServiceReferences();
                     for (int i = 0; i < refs.length; i++) {
                         invokeCallback(m_callbacks[j], refs[i], pojo);
                     }
                 } else {
-                    ServiceReference ref = getServiceReference();
-                    if (ref != null) {
-                        invokeCallback(m_callbacks[j], ref, pojo);
-                    }
+                    // Take the first reference.
+                    invokeCallback(m_callbacks[j], refs[0], pojo);
                 }
             }
         }
@@ -292,9 +302,15 @@
                 if (m_supportNullable) {
                     // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has
                     // access to the service specification.
-                    m_nullable =
+                    try { 
+                        m_nullable =
                             Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] {
                                     getSpecification(), Nullable.class }, new NullableObject()); // NOPMD
+                    } catch (NoClassDefFoundError e) {
+                        // 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());
+                    }
                 }
             } else {
                 // Create the default-implementation object.