Add some more methods to SecureAction that allow for reflection and unsetting URLStreamHandlerFractory.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@634290 13f79535-47bb-0310-9956-ffa450edef68
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 0134238..910c118 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
@@ -19,14 +19,16 @@
 package org.apache.felix.framework.util;
 
 import java.io.*;
-import java.lang.reflect.Method;
+import java.lang.reflect.*;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
 import java.net.*;
 import java.security.*;
+import java.util.Hashtable;
 import java.util.jar.JarFile;
 
 import org.apache.felix.framework.searchpolicy.ContentClassLoader;
 import org.apache.felix.framework.searchpolicy.ContentLoaderImpl;
-import org.apache.felix.framework.util.JarFileX;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -680,6 +682,232 @@
         }
     }
     
+    public Constructor getConstructor(Class target, Class[] types) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.GET_CONSTRUCTOR_ACTION, target, types);
+            try
+            {
+                return (Constructor) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return target.getConstructor(types);
+        }
+    }
+    
+    public Method getMethod(Class target, String method, Class[] types) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.GET_METHOD_ACTION, target, method, types);
+            try
+            {
+                return (Method) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return target.getMethod(method, types);
+        }
+    }
+    
+    public Method getDeclaredMethod(Class target, String method, Class[] types) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.GET_DECLAREDMETHOD_ACTION, target, method, types);
+            try
+            {
+                return (Method) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return target.getDeclaredMethod(method, types);
+        }
+    }
+    
+    public Object invoke(Method method, Object target, Object[] params) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_METHOD_ACTION, method, target, params);
+            try
+            {
+                return AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            method.setAccessible(true);
+            return method.invoke(target, params);
+        }
+    }
+    
+    public Object invoke(Constructor constructor, Object[] params) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_CONSTRUCTOR_ACTION, constructor, params);
+            try
+            {
+                return AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            constructor.setAccessible(true);
+            return constructor.newInstance(params);
+        }
+    }
+
+    public Object getDeclaredField(Class targetClass, String name, Object target) 
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.GET_FIELD_ACTION, targetClass, name, target);
+            try
+            {
+                return AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            Field field = targetClass.getDeclaredField(name);
+            field.setAccessible(true);
+            
+            return field.get(target);
+        }
+    }
+
+    public Object swapStaticFieldIfNotClass(Class targetClazz, 
+        Class targetType, Class condition, String lockName) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.SWAP_FIELD_ACTION, targetClazz, targetType, 
+                condition, lockName);
+            try
+            {
+                return AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return _swapStaticFieldIfNotClass(targetClazz, targetType, 
+                condition, lockName);
+        }
+    }
+    
+    private static Object _swapStaticFieldIfNotClass(Class targetClazz, 
+        Class targetType, Class condition, String lockName) throws Exception
+    {
+        Object lock = null;
+        if (lockName != null)
+        {
+            try 
+            {
+                Field lockField = 
+                    targetClazz.getDeclaredField(lockName); 
+                lockField.setAccessible(true);
+                lock = lockField.get(null);
+            } 
+            catch (NoSuchFieldException ex) 
+            {
+            }
+        }
+        if (lock == null)
+        {
+            lock = targetClazz;
+        }
+        synchronized (lock)
+        {
+            Field[] fields = targetClazz.getDeclaredFields();
+
+            Object result = null;
+            for (int i = 0; (i < fields.length) && (result == null); i++)
+            {
+                if (Modifier.isStatic(fields[i].getModifiers()) && 
+                    (fields[i].getType() == targetType))
+                {
+                    fields[i].setAccessible(true);
+                    
+                    result = fields[i].get(null);
+                    
+                    if (result != null)
+                    {
+                        if ((condition == null) ||
+                            !result.getClass().getName().equals(condition.getName()))
+                        {
+                            fields[i].set(null, null);
+                        }
+                    }
+                }
+            }
+            if (result != null)
+            {
+                if ((condition == null) || !result.getClass().getName().equals(condition.getName()))
+                {
+                    // reset cache
+                    for (int i = 0; i < fields.length; i++)
+                    {
+                        if (Modifier.isStatic(fields[i].getModifiers()) && 
+                            (fields[i].getType() == Hashtable.class))
+                        {
+                            fields[i].setAccessible(true);
+                            Hashtable cache = (Hashtable) fields[i].get(null);
+                            if (cache != null)
+                            {
+                                cache.clear();
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+        }
+        return null;
+    }
+    
     private static class Actions implements PrivilegedExceptionAction
     {
         public static final int GET_PROPERTY_ACTION = 0;
@@ -708,6 +936,13 @@
         public static final int OPEN_URLCONNECTION_ACTION = 23;
         public static final int OPEN_JARURLCONNECTIONJAR_ACTION = 24;
         public static final int ADD_EXTENSION_URL = 25;
+        public static final int GET_CONSTRUCTOR_ACTION = 26;
+        public static final int GET_METHOD_ACTION = 27;
+        public static final int INVOKE_METHOD_ACTION = 28;
+        public static final int INVOKE_CONSTRUCTOR_ACTION = 29;
+        public static final int SWAP_FIELD_ACTION = 30;
+        public static final int GET_FIELD_ACTION = 31;
+        public static final int GET_DECLAREDMETHOD_ACTION = 32;
 
         private int m_action = -1;
         private Object m_arg1 = null;
@@ -887,7 +1122,40 @@
                     addURL.setAccessible(true);
                     addURL.invoke(m_arg2, new Object[]{m_arg1});
                 }
-
+                else if (m_action == GET_CONSTRUCTOR_ACTION)
+                {
+                    return ((Class) m_arg1).getConstructor((Class[]) m_arg2);
+                }
+                else if (m_action == GET_METHOD_ACTION)
+                {
+                    return ((Class) m_arg1).getMethod((String) m_arg2, (Class[]) m_arg3);
+                }
+                else if (m_action == INVOKE_METHOD_ACTION)
+                {
+                    ((Method) m_arg1).setAccessible(true);
+                    return ((Method) m_arg1).invoke(m_arg2, (Object[]) m_arg3);
+                }
+                else if (m_action == INVOKE_CONSTRUCTOR_ACTION)
+                {
+                    ((Constructor) m_arg1).setAccessible(true);
+                    return ((Constructor) m_arg1).newInstance((Object[]) m_arg2);
+                }
+                else if (m_action == SWAP_FIELD_ACTION)
+                {
+                    return _swapStaticFieldIfNotClass((Class) m_arg1, 
+                        (Class) m_arg2, (Class) m_arg3, (String) m_arg4);
+                }
+                else if (m_action == GET_FIELD_ACTION)
+                {
+                    Field field = ((Class) m_arg1).getDeclaredField((String) m_arg2);
+                    field.setAccessible(true);
+                    return field.get(m_arg3);
+                }
+                else if (m_action == GET_DECLAREDMETHOD_ACTION)
+                {
+                    return ((Class) m_arg1).getDeclaredMethod((String) m_arg2, (Class[]) m_arg3);
+                }
+                
                 return null;
             }
             finally