Make sure to call service hooks in privileged blocks. (FELIX-3056)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1153170 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 0d6e7fa..c879761 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3098,7 +3098,7 @@
                 {
                     try
                     {
-                        lh.removed(removed);
+                        m_secureAction.invokeServiceListenerHookRemoved(lh, removed);
                     }
                     catch (Throwable th)
                     {
@@ -3124,7 +3124,7 @@
             {
                 try
                 {
-                    lh.added(added);
+                    m_secureAction.invokeServiceListenerHookAdded(lh, added);
                 }
                 catch (Throwable th)
                 {
@@ -3165,7 +3165,7 @@
                 {
                     try
                     {
-                        lh.removed(removed);
+                        m_secureAction.invokeServiceListenerHookRemoved(lh, removed);
                     }
                     catch (Throwable th)
                     {
@@ -3291,7 +3291,8 @@
             {
                 try
                 {
-                    lh.added(m_dispatcher.getAllServiceListeners());
+                    m_secureAction.invokeServiceListenerHookAdded(
+                        lh, m_dispatcher.getAllServiceListeners());
                 }
                 catch (Throwable th)
                 {
@@ -3374,7 +3375,9 @@
             {
                 try
                 {
-                    fh.find(bundle._getBundleContext(),
+                    m_secureAction.invokeServiceFindHook(
+                        fh,
+                        bundle._getBundleContext(),
                         className,
                         expr,
                         !checkAssignable,
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index 05e01cb..a3403a0 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -587,7 +587,8 @@
                     {
                         try
                         {
-                            elh.event(event, shrinkableMap);
+                            m_secureAction.invokeServiceEventListenerHook(
+                                elh, event, shrinkableMap);
                         }
                         catch (Throwable th)
                         {
@@ -665,8 +666,9 @@
                         {
                             if (eh instanceof org.osgi.framework.hooks.service.EventHook)
                             {
-                                ((org.osgi.framework.hooks.service.EventHook)
-                                    eh).event((ServiceEvent) event, shrinkable);
+                                m_secureAction.invokeServiceEventHook(
+                                    (org.osgi.framework.hooks.service.EventHook) eh,
+                                    (ServiceEvent) event, shrinkable);
                             }
                             else if (eh instanceof org.osgi.framework.hooks.bundle.EventHook)
                             {
diff --git a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index 4a27c47..191879f 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -25,11 +25,15 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Map;
 import org.osgi.framework.Bundle;
 
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.ListenerHook;
 
 /**
  * <p>
@@ -1115,6 +1119,130 @@
         }
     }
 
+    public void invokeServiceEventHook(
+        org.osgi.framework.hooks.service.EventHook eh,
+        ServiceEvent event, Collection<BundleContext> contexts)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_SERVICE_EVENT_HOOK, eh, contexts);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            eh.event(event, contexts);
+        }
+    }
+
+    public void invokeServiceFindHook(
+        org.osgi.framework.hooks.service.FindHook fh,
+        BundleContext context, String name, String filter,
+        boolean allServices, Collection<ServiceReference<?>> references)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(
+                Actions.INVOKE_SERVICE_EVENT_HOOK, fh, context, name, filter,
+                (allServices) ? Boolean.TRUE : Boolean.FALSE, references);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            fh.find(context, name, filter, allServices, references);
+        }
+    }
+
+    public void invokeServiceListenerHookAdded(
+        org.osgi.framework.hooks.service.ListenerHook lh,
+        Collection<ListenerHook.ListenerInfo> listeners)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_ADDED, lh, listeners);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            lh.added(listeners);
+        }
+    }
+
+    public void invokeServiceListenerHookRemoved(
+        org.osgi.framework.hooks.service.ListenerHook lh,
+        Collection<ListenerHook.ListenerInfo> listeners)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_REMOVED, lh, listeners);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            lh.removed(listeners);
+        }
+    }
+
+    public void invokeServiceEventListenerHook(
+        org.osgi.framework.hooks.service.EventListenerHook elh,
+        ServiceEvent event,
+        Map<BundleContext, Collection<ListenerHook.ListenerInfo>> listeners)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_SERVICE_EVENT_LISTENER_HOOK, elh, listeners);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            elh.event(event, listeners);
+        }
+    }
+
     private static class Actions implements PrivilegedExceptionAction
     {
         public static final int INITIALIZE_CONTEXT_ACTION = 0;
@@ -1160,6 +1288,11 @@
         public static final int INVOKE_BUNDLE_FIND_HOOK = 40;
         public static final int INVOKE_BUNDLE_EVENT_HOOK = 41;
         public static final int INVOKE_WEAVING_HOOK = 42;
+        public static final int INVOKE_SERVICE_EVENT_HOOK = 43;
+        public static final int INVOKE_SERVICE_FIND_HOOK = 44;
+        public static final int INVOKE_SERVICE_LISTENER_HOOK_ADDED = 45;
+        public static final int INVOKE_SERVICE_LISTENER_HOOK_REMOVED = 46;
+        public static final int INVOKE_SERVICE_EVENT_LISTENER_HOOK = 47;
 
         private int m_action = -1;
         private Object m_arg1 = null;
@@ -1167,6 +1300,7 @@
         private Object m_arg3 = null;
         private Object m_arg4 = null;
         private Object m_arg5 = null;
+        private Object m_arg6 = null;
 
         public void set(int action)
         {
@@ -1215,6 +1349,18 @@
             m_arg5 = arg5;
         }
 
+        public void set(int action, Object arg1, Object arg2, Object arg3,
+            Object arg4, Object arg5, Object arg6)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_arg3 = arg3;
+            m_arg4 = arg4;
+            m_arg5 = arg5;
+            m_arg6 = arg6;
+        }
+
         private void unset()
         {
             m_action = -1;
@@ -1223,6 +1369,7 @@
             m_arg3 = null;
             m_arg4 = null;
             m_arg5 = null;
+            m_arg6 = null;
         }
 
         public Object run() throws Exception
@@ -1233,6 +1380,7 @@
             Object arg3 = m_arg3;
             Object arg4 = m_arg4;
             Object arg5 = m_arg5;
+            Object arg6 = m_arg6;
 
             unset();
 
@@ -1345,6 +1493,29 @@
                     ((org.osgi.framework.hooks.weaving.WeavingHook) arg1).weave(
                         (org.osgi.framework.hooks.weaving.WovenClass) arg2);
                     return null;
+                case INVOKE_SERVICE_EVENT_HOOK:
+                    ((org.osgi.framework.hooks.service.EventHook) arg1).event(
+                        (ServiceEvent) arg2, (Collection<BundleContext>) arg3);
+                    return null;
+                case INVOKE_SERVICE_FIND_HOOK:
+                    ((org.osgi.framework.hooks.service.FindHook) arg1).find(
+                        (BundleContext) arg2, (String) arg3, (String) arg4,
+                        ((Boolean) arg5).booleanValue(),
+                        (Collection<ServiceReference<?>>) arg6);
+                    return null;
+                case INVOKE_SERVICE_LISTENER_HOOK_ADDED:
+                    ((org.osgi.framework.hooks.service.ListenerHook) arg1).added(
+                        (Collection<ListenerHook.ListenerInfo>) arg2);
+                    return null;
+                case INVOKE_SERVICE_LISTENER_HOOK_REMOVED:
+                    ((org.osgi.framework.hooks.service.ListenerHook) arg1).removed(
+                        (Collection<ListenerHook.ListenerInfo>) arg2);
+                    return null;
+                case INVOKE_SERVICE_EVENT_LISTENER_HOOK:
+                    ((org.osgi.framework.hooks.service.EventListenerHook) arg1).event(
+                        (ServiceEvent) arg2,
+                        (Map<BundleContext, Collection<ListenerHook.ListenerInfo>>) arg3);
+                    return null;
             }
 
             return null;