Implement support for service exceptions for service factory handling. (FELIX-1250)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@785779 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 4b200eb..1201542 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2905,6 +2905,7 @@
         // Check that the bundle has permission to get at least
         // one of the service interfaces; the objectClass property
         // of the service stores its service interfaces.
+// TODO: SECURITY - This check does not look complete.
         String[] objectClass = (String[])
             ref.getProperty(Constants.OBJECTCLASS);
         if (objectClass == null)
@@ -2912,7 +2913,16 @@
             return null;
         }
 
-        return m_registry.getService(bundle, ref);
+        try
+        {
+            return m_registry.getService(bundle, ref);
+        }
+        catch (ServiceException ex)
+        {
+            fireFrameworkEvent(FrameworkEvent.ERROR, ref.getBundle(), ex);
+        }
+
+        return null;
     }
 
     protected boolean ungetService(Bundle bundle, ServiceReference ref)
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index 8c47b37..8673eb6 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -19,6 +19,7 @@
 package org.apache.felix.framework;
 
 import java.security.AccessController;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.*;
 
@@ -194,25 +195,33 @@
         // let it create the service object.
         if (m_factory != null)
         {
+            Object svcObj = null;
             try
             {
                 if (System.getSecurityManager() != null)
                 {
-                    return AccessController.doPrivileged(
+                    svcObj = AccessController.doPrivileged(
                         new ServiceFactoryPrivileged(acqBundle, null));
                 }
                 else
                 {
-                    return getFactoryUnchecked(acqBundle);
+                    svcObj = getFactoryUnchecked(acqBundle);
                 }
             }
-            catch (Exception ex)
+            catch (PrivilegedActionException ex)
             {
-                m_registry.getLogger().log(
-                    Logger.LOG_ERROR,
-                    "ServiceRegistrationImpl: Error getting service.", ex);
-                return null;
+                if (ex.getException() instanceof ServiceException)
+                {
+                    throw (ServiceException) ex.getException();
+                }
+                else
+                {
+                    throw new ServiceException(
+                        "Service factory exception: " + ex.getException().getMessage(),
+                        ServiceException.FACTORY_EXCEPTION, ex.getException());
+                }
             }
+            return svcObj;
         }
         else
         {
@@ -279,7 +288,17 @@
 
     private Object getFactoryUnchecked(Bundle bundle)
     {
-        Object svcObj = m_factory.getService(bundle, this);
+        Object svcObj = null;
+        try
+        {
+            svcObj = m_factory.getService(bundle, this);
+        }
+        catch (Throwable th)
+        {
+            throw new ServiceException(
+                "Service factory exception: " + th.getMessage(),
+                ServiceException.FACTORY_EXCEPTION, th);
+        }
         if (svcObj != null)
         {
             for (int i = 0; i < m_classes.length; i++)
@@ -287,10 +306,26 @@
                 Class clazz = Util.loadClassUsingClass(svcObj.getClass(), m_classes[i]);
                 if ((clazz == null) || !clazz.isAssignableFrom(svcObj.getClass()))
                 {
-                    return null;
+                    if (clazz == null)
+                    {
+                        throw new ServiceException(
+                            "Service cannot be cast due to missing class: " + m_classes[i],
+                            ServiceException.FACTORY_ERROR);
+                    }
+                    else
+                    {
+                        throw new ServiceException(
+                            "Service cannot be cast: " + m_classes[i],
+                            ServiceException.FACTORY_ERROR);
+                    }
                 }
             }
         }
+        else
+        {
+            throw new ServiceException(
+                "Service factory returned null.", ServiceException.FACTORY_ERROR);
+        }
         return svcObj;
     }