You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2013/04/04 11:43:37 UTC

svn commit: r1464402 [9/11] - in /ace/trunk: org.apache.ace.deployment.api/ org.apache.ace.deployment.deploymentadmin/ org.apache.ace.deployment.itest/ org.apache.ace.deployment.itest/src/org/apache/ace/it/deployment/ org.apache.ace.deployment.provider...

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/SecureAction.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/SecureAction.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/SecureAction.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/SecureAction.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,1676 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.security.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.zip.ZipFile;
+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.resolver.ResolverHook;
+import org.osgi.framework.hooks.service.ListenerHook;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+
+/**
+ * <p>
+ * This is a utility class to centralize all action that should be performed
+ * in a <tt>doPrivileged()</tt> block. To perform a secure action, simply
+ * create an instance of this class and use the specific method to perform
+ * the desired action. When an instance is created, this class will capture
+ * the security context and will then use that context when checking for
+ * permission to perform the action. Instances of this class should not be
+ * passed around since they may grant the receiver a capability to perform
+ * privileged actions.
+ * </p>
+**/
+public class SecureAction
+{
+    private static final ThreadLocal m_actions = new ThreadLocal()
+    {
+        public Object initialValue()
+        {
+            return new Actions();
+        }
+    };
+
+    protected static transient int BUFSIZE = 4096;
+
+    private AccessControlContext m_acc = null;
+
+    public SecureAction()
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.INITIALIZE_CONTEXT_ACTION, null);
+                m_acc = (AccessControlContext) AccessController.doPrivileged(actions);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            m_acc = AccessController.getContext();
+        }
+    }
+
+    public String getSystemProperty(String name, String def)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_PROPERTY_ACTION, name, def);
+                return (String) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return System.getProperty(name, def);
+        }
+    }
+
+    public ClassLoader getParentClassLoader(ClassLoader loader)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_PARENT_CLASS_LOADER_ACTION, loader);
+                return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return loader.getParent();
+        }
+    }
+
+    public ClassLoader getSystemClassLoader()
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_SYSTEM_CLASS_LOADER_ACTION);
+                return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return ClassLoader.getSystemClassLoader();
+        }
+    }
+
+    public ClassLoader getClassLoader(Class clazz)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_CLASS_LOADER_ACTION, clazz);
+                return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return clazz.getClassLoader();
+        }
+    }
+
+    public Class forName(String name) throws ClassNotFoundException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.FOR_NAME_ACTION, name);
+                return (Class) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof ClassNotFoundException)
+                {
+                    throw (ClassNotFoundException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return Class.forName(name);
+        }
+    }
+
+    public URL createURL(String protocol, String host,
+        int port, String path, URLStreamHandler handler)
+        throws MalformedURLException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.CREATE_URL_ACTION, protocol, host,
+                    new Integer(port), path, handler);
+                return (URL) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof MalformedURLException)
+                {
+                    throw (MalformedURLException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new URL(protocol, host, port, path, handler);
+        }
+    }
+
+    public URL createURL(URL context, String spec, URLStreamHandler handler)
+        throws MalformedURLException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.CREATE_URL_WITH_CONTEXT_ACTION, context,
+                    spec, handler);
+                return (URL) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof MalformedURLException)
+                {
+                    throw (MalformedURLException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new URL(context, spec, handler);
+        }
+    }
+
+    public Process exec(String command) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.EXEC_ACTION, command);
+                return (Process) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return Runtime.getRuntime().exec(command);
+        }
+    }
+
+    public String getAbsolutePath(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_ABSOLUTE_PATH_ACTION, file);
+                return (String) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.getAbsolutePath();
+        }
+    }
+
+    public boolean fileExists(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.FILE_EXISTS_ACTION, file);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.exists();
+        }
+    }
+
+    public boolean isFileDirectory(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.FILE_IS_DIRECTORY_ACTION, file);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.isDirectory();
+        }
+    }
+
+    public boolean mkdir(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.MAKE_DIRECTORY_ACTION, file);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.mkdir();
+        }
+    }
+
+    public boolean mkdirs(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.MAKE_DIRECTORIES_ACTION, file);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.mkdirs();
+        }
+    }
+
+    public File[] listDirectory(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.LIST_DIRECTORY_ACTION, file);
+                return (File[]) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.listFiles();
+        }
+    }
+
+    public boolean renameFile(File oldFile, File newFile)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.RENAME_FILE_ACTION, oldFile, newFile);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return oldFile.renameTo(newFile);
+        }
+    }
+
+    public FileInputStream getFileInputStream(File file) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_FILE_INPUT_ACTION, file);
+                return (FileInputStream) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new FileInputStream(file);
+        }
+    }
+
+    public FileOutputStream getFileOutputStream(File file) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_FILE_OUTPUT_ACTION, file);
+                return (FileOutputStream) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new FileOutputStream(file);
+        }
+    }
+
+    public URI toURI(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.TO_URI_ACTION, file);
+                return (URI) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.toURI();
+        }
+    }
+
+    public InputStream getURLConnectionInputStream(URLConnection conn)
+        throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_URL_INPUT_ACTION, conn);
+                return (InputStream) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return conn.getInputStream();
+        }
+    }
+
+    public boolean deleteFile(File target)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.DELETE_FILE_ACTION, target);
+                return ((Boolean) AccessController.doPrivileged(actions, m_acc))
+                    .booleanValue();
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return target.delete();
+        }
+    }
+
+    public File createTempFile(String prefix, String suffix, File dir)
+        throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.CREATE_TMPFILE_ACTION, prefix, suffix, dir);
+                return (File) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return File.createTempFile(prefix, suffix, dir);
+        }
+    }
+
+    public URLConnection openURLConnection(URL url) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.OPEN_URLCONNECTION_ACTION, url);
+                return (URLConnection) AccessController.doPrivileged(actions,
+                    m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return url.openConnection();
+        }
+    }
+
+    public ZipFile openZipFile(File file) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.OPEN_ZIPFILE_ACTION, file);
+                return (ZipFile) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new ZipFile(file);
+        }
+    }
+
+    public void startActivator(BundleActivator activator, BundleContext context)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.START_ACTIVATOR_ACTION, activator, context);
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw ex.getException();
+            }
+        }
+        else
+        {
+            activator.start(context);
+        }
+    }
+
+    public void stopActivator(BundleActivator activator, BundleContext context)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.STOP_ACTIVATOR_ACTION, activator, context);
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw ex.getException();
+            }
+        }
+        else
+        {
+            activator.stop(context);
+        }
+    }
+
+    public Policy getPolicy()
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.GET_POLICY_ACTION, null);
+                return (Policy) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return Policy.getPolicy();
+        }
+    }
+
+    public void addURLToURLClassLoader(URL extension, ClassLoader loader) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.ADD_EXTENSION_URL_ACTION, extension, loader);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            Method addURL =
+                URLClassLoader.class.getDeclaredMethod("addURL",
+                new Class[] {URL.class});
+            addURL.setAccessible(true);
+            addURL.invoke(loader, new Object[]{extension});
+        }
+    }
+
+    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 Constructor getDeclaredConstructor(Class target, Class[] types) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.GET_DECLARED_CONSTRUCTOR_ACTION, target, types);
+            try
+            {
+                return (Constructor) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return target.getDeclaredConstructor(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_DECLARED_METHOD_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 void setAccesssible(AccessibleObject ao)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.SET_ACCESSIBLE_ACTION, ao);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw (RuntimeException) e.getException();
+            }
+        }
+        else
+        {
+            ao.setAccessible(true);
+        }
+    }
+
+    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 invokeDirect(Method method, Object target, Object[] params) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_DIRECTMETHOD_ACTION, method, target, params);
+            try
+            {
+                return AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            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
+        {
+            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;
+    }
+
+    public void flush(Class targetClazz, Object lock) throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.FLUSH_FIELD_ACTION, targetClazz, lock);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            _flush(targetClazz, lock);
+        }
+    }
+
+    private static void _flush(Class targetClazz, Object lock) throws Exception
+    {
+        synchronized (lock)
+        {
+            Field[] fields = targetClazz.getDeclaredFields();
+            // reset cache
+            for (int i = 0; i < fields.length; i++)
+            {
+                if (Modifier.isStatic(fields[i].getModifiers()) &&
+                    ((fields[i].getType() == Hashtable.class) || (fields[i].getType() == HashMap.class)))
+                {
+                    fields[i].setAccessible(true);
+                    if (fields[i].getType() == Hashtable.class)
+                    {
+                        Hashtable cache = (Hashtable) fields[i].get(null);
+                        if (cache != null)
+                        {
+                            cache.clear();
+                        }
+                    }
+                    else
+                    {
+                        HashMap cache = (HashMap) fields[i].get(null);
+                        if (cache != null)
+                        {
+                            cache.clear();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+   /* public void invokeBundleFindHook(
+        org.osgi.framework.hooks.bundle.FindHook fh,
+        BundleContext bc, Collection<Bundle> bundles)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_BUNDLE_FIND_HOOK, fh, bc, bundles);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            fh.find(bc, bundles);
+        }
+    }
+
+    public void invokeBundleEventHook(
+        org.osgi.framework.hooks.bundle.EventHook eh,
+        BundleEvent event, Collection<BundleContext> contexts)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_BUNDLE_EVENT_HOOK, eh, contexts);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            eh.event(event, contexts);
+        }
+    }
+
+    public void invokeWeavingHook(
+        org.osgi.framework.hooks.weaving.WeavingHook wh,
+        org.osgi.framework.hooks.weaving.WovenClass wc)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_WEAVING_HOOK, wh, wc);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            wh.weave(wc);
+        }
+    }
+
+    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);
+        }
+    }
+
+    public ResolverHook invokeResolverHookFactory(
+        org.osgi.framework.hooks.resolver.ResolverHookFactory rhf,
+        Collection<BundleRevision> triggers)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_RESOLVER_HOOK_FACTORY, rhf, triggers);
+            try
+            {
+                return (ResolverHook) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            return rhf.begin(triggers);
+        }
+    }
+
+    public void invokeResolverHookResolvable(
+        org.osgi.framework.hooks.resolver.ResolverHook rh,
+        Collection<BundleRevision> candidates)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_RESOLVER_HOOK_RESOLVABLE, rh, candidates);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            rh.filterResolvable(candidates);
+        }
+    }
+
+    public void invokeResolverHookSingleton(
+        org.osgi.framework.hooks.resolver.ResolverHook rh,
+        BundleCapability singleton,
+        Collection<BundleCapability> collisions)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_RESOLVER_HOOK_SINGLETON, rh, singleton, collisions);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            rh.filterSingletonCollisions(singleton, collisions);
+        }
+    }
+
+    public void invokeResolverHookMatches(
+        org.osgi.framework.hooks.resolver.ResolverHook rh,
+        BundleRequirement req,
+        Collection<BundleCapability> candidates)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_RESOLVER_HOOK_MATCHES, rh, req, candidates);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            rh.filterMatches(req, candidates);
+        }
+    }
+
+    public void invokeResolverHookEnd(
+        org.osgi.framework.hooks.resolver.ResolverHook rh)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_RESOLVER_HOOK_END, rh);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            rh.end();
+        }
+    }
+*/
+    private static class Actions implements PrivilegedExceptionAction
+    {
+        public static final int INITIALIZE_CONTEXT_ACTION = 0;
+        public static final int ADD_EXTENSION_URL_ACTION = 1;
+        public static final int CREATE_TMPFILE_ACTION = 2;
+        public static final int CREATE_URL_ACTION = 3;
+        public static final int CREATE_URL_WITH_CONTEXT_ACTION = 4;
+        public static final int DELETE_FILE_ACTION = 5;
+        public static final int EXEC_ACTION = 6;
+        public static final int FILE_EXISTS_ACTION = 7;
+        public static final int FILE_IS_DIRECTORY_ACTION = 8;
+        public static final int FOR_NAME_ACTION = 9;
+        public static final int GET_ABSOLUTE_PATH_ACTION = 10;
+        public static final int GET_CONSTRUCTOR_ACTION = 11;
+        public static final int GET_DECLARED_CONSTRUCTOR_ACTION = 12;
+        public static final int GET_DECLARED_METHOD_ACTION = 13;
+        public static final int GET_FIELD_ACTION = 14;
+        public static final int GET_FILE_INPUT_ACTION = 15;
+        public static final int GET_FILE_OUTPUT_ACTION = 16;
+        public static final int TO_URI_ACTION = 17;
+        public static final int GET_METHOD_ACTION = 18;
+        public static final int GET_POLICY_ACTION = 19;
+        public static final int GET_PROPERTY_ACTION = 20;
+        public static final int GET_PARENT_CLASS_LOADER_ACTION = 21;
+        public static final int GET_SYSTEM_CLASS_LOADER_ACTION = 22;
+        public static final int GET_URL_INPUT_ACTION = 23;
+        public static final int INVOKE_CONSTRUCTOR_ACTION = 24;
+        public static final int INVOKE_DIRECTMETHOD_ACTION = 25;
+        public static final int INVOKE_METHOD_ACTION = 26;
+        public static final int LIST_DIRECTORY_ACTION = 27;
+        public static final int MAKE_DIRECTORIES_ACTION = 28;
+        public static final int MAKE_DIRECTORY_ACTION = 29;
+        public static final int OPEN_ZIPFILE_ACTION = 30;
+        public static final int OPEN_URLCONNECTION_ACTION = 31;
+        public static final int RENAME_FILE_ACTION = 32;
+        public static final int SET_ACCESSIBLE_ACTION = 33;
+        public static final int START_ACTIVATOR_ACTION = 34;
+        public static final int STOP_ACTIVATOR_ACTION = 35;
+        public static final int SWAP_FIELD_ACTION = 36;
+        public static final int SYSTEM_EXIT_ACTION = 37;
+        public static final int FLUSH_FIELD_ACTION = 38;
+        public static final int GET_CLASS_LOADER_ACTION = 39;
+        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;
+        public static final int INVOKE_RESOLVER_HOOK_FACTORY = 48;
+        public static final int INVOKE_RESOLVER_HOOK_RESOLVABLE = 49;
+        public static final int INVOKE_RESOLVER_HOOK_SINGLETON = 50;
+        public static final int INVOKE_RESOLVER_HOOK_MATCHES = 51;
+        public static final int INVOKE_RESOLVER_HOOK_END = 52;
+
+        private int m_action = -1;
+        private Object m_arg1 = null;
+        private Object m_arg2 = null;
+        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)
+        {
+            m_action = action;
+        }
+
+        public void set(int action, Object arg1)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+        }
+
+        public void set(int action, Object arg1, Object arg2)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+        }
+
+        public void set(int action, Object arg1, Object arg2, Object arg3)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_arg3 = arg3;
+        }
+
+        public void set(int action, Object arg1, Object arg2, Object arg3,
+            Object arg4)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_arg3 = arg3;
+            m_arg4 = arg4;
+        }
+
+        public void set(int action, Object arg1, Object arg2, Object arg3,
+            Object arg4, Object arg5)
+        {
+            m_action = action;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_arg3 = arg3;
+            m_arg4 = arg4;
+            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;
+            m_arg1 = null;
+            m_arg2 = null;
+            m_arg3 = null;
+            m_arg4 = null;
+            m_arg5 = null;
+            m_arg6 = null;
+        }
+
+        public Object run() throws Exception
+        {
+            int action =  m_action;
+            Object arg1 = m_arg1;
+            Object arg2 = m_arg2;
+            Object arg3 = m_arg3;
+            Object arg4 = m_arg4;
+            Object arg5 = m_arg5;
+            Object arg6 = m_arg6;
+
+            unset();
+
+            switch (action)
+            {
+                case INITIALIZE_CONTEXT_ACTION:
+                    return AccessController.getContext();
+                case ADD_EXTENSION_URL_ACTION:
+                    Method addURL =
+                        URLClassLoader.class.getDeclaredMethod("addURL",
+                        new Class[] {URL.class});
+                    addURL.setAccessible(true);
+                    addURL.invoke(arg2, new Object[]{arg1});
+                    return null;
+                case CREATE_TMPFILE_ACTION:
+                    return File.createTempFile((String) arg1, (String) arg2, (File) arg3);
+                case CREATE_URL_ACTION:
+                    return new URL((String) arg1, (String) arg2,
+                        ((Integer) arg3).intValue(), (String) arg4,
+                        (URLStreamHandler) arg5);
+                case CREATE_URL_WITH_CONTEXT_ACTION:
+                    return new URL((URL) arg1, (String) arg2, (URLStreamHandler) arg3);
+                case DELETE_FILE_ACTION:
+                    return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE;
+                case EXEC_ACTION:
+                    return Runtime.getRuntime().exec((String) arg1);
+                case FILE_EXISTS_ACTION:
+                    return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE;
+                case FILE_IS_DIRECTORY_ACTION:
+                    return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE;
+                case FOR_NAME_ACTION:
+                    return Class.forName((String) arg1);
+                case GET_ABSOLUTE_PATH_ACTION:
+                    return ((File) arg1).getAbsolutePath();
+                case GET_CONSTRUCTOR_ACTION:
+                    return ((Class) arg1).getConstructor((Class[]) arg2);
+                case GET_DECLARED_CONSTRUCTOR_ACTION:
+                    return ((Class) arg1).getDeclaredConstructor((Class[]) arg2);
+                case GET_DECLARED_METHOD_ACTION:
+                    return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3);
+                case GET_FIELD_ACTION:
+                    Field field = ((Class) arg1).getDeclaredField((String) arg2);
+                    field.setAccessible(true);
+                    return field.get(arg3);
+                case GET_FILE_INPUT_ACTION:
+                    return new FileInputStream((File) arg1);
+                case GET_FILE_OUTPUT_ACTION:
+                    return new FileOutputStream((File) arg1);
+                case TO_URI_ACTION:
+                    return ((File) arg1).toURI();
+                case GET_METHOD_ACTION:
+                    return ((Class) arg1).getMethod((String) arg2, (Class[]) arg3);
+                case GET_POLICY_ACTION:
+                    return Policy.getPolicy();
+                case GET_PROPERTY_ACTION:
+                    return System.getProperty((String) arg1, (String) arg2);
+                case GET_PARENT_CLASS_LOADER_ACTION:
+                    return ((ClassLoader) arg1).getParent();
+                case GET_SYSTEM_CLASS_LOADER_ACTION:
+                    return ClassLoader.getSystemClassLoader();
+                case GET_URL_INPUT_ACTION:
+                    return ((URLConnection) arg1).getInputStream();
+                case INVOKE_CONSTRUCTOR_ACTION:
+                    return ((Constructor) arg1).newInstance((Object[]) arg2);
+                case INVOKE_DIRECTMETHOD_ACTION:
+                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
+                case INVOKE_METHOD_ACTION:
+                    ((Method) arg1).setAccessible(true);
+                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
+                case LIST_DIRECTORY_ACTION:
+                    return ((File) arg1).listFiles();
+                case MAKE_DIRECTORIES_ACTION:
+                    return ((File) arg1).mkdirs() ? Boolean.TRUE : Boolean.FALSE;
+                case MAKE_DIRECTORY_ACTION:
+                    return ((File) arg1).mkdir() ? Boolean.TRUE : Boolean.FALSE;
+                case OPEN_ZIPFILE_ACTION:
+                    return new ZipFile((File) arg1);
+                case OPEN_URLCONNECTION_ACTION:
+                    return ((URL) arg1).openConnection();
+                case RENAME_FILE_ACTION:
+                    return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE;
+                case SET_ACCESSIBLE_ACTION:
+                    ((AccessibleObject) arg1).setAccessible(true);
+                    return null;
+                case START_ACTIVATOR_ACTION:
+                    ((BundleActivator) arg1).start((BundleContext) arg2);
+                    return null;
+                case STOP_ACTIVATOR_ACTION:
+                    ((BundleActivator) arg1).stop((BundleContext) arg2);
+                    return null;
+                case SWAP_FIELD_ACTION:
+                    return _swapStaticFieldIfNotClass((Class) arg1,
+                        (Class) arg2, (Class) arg3, (String) arg4);
+                case SYSTEM_EXIT_ACTION:
+                    System.exit(((Integer) arg1).intValue());
+                case FLUSH_FIELD_ACTION:
+                    _flush(((Class) arg1), arg2);
+                    return null;
+                case GET_CLASS_LOADER_ACTION:
+                    return ((Class) arg1).getClassLoader();
+               /* case INVOKE_BUNDLE_FIND_HOOK:
+                    ((org.osgi.framework.hooks.bundle.FindHook) arg1).find(
+                        (BundleContext) arg2, (Collection<Bundle>) arg3);
+                    return null;
+                case INVOKE_BUNDLE_EVENT_HOOK:
+                    ((org.osgi.framework.hooks.bundle.EventHook) arg1).event(
+                        (BundleEvent) arg2, (Collection<BundleContext>) arg3);
+                    return null;
+                case INVOKE_WEAVING_HOOK:
+                    ((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;
+                case INVOKE_RESOLVER_HOOK_FACTORY:
+                    return ((org.osgi.framework.hooks.resolver.ResolverHookFactory) arg1).begin(
+                        (Collection<BundleRevision>) arg2);
+                case INVOKE_RESOLVER_HOOK_RESOLVABLE:
+                    ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).filterResolvable(
+                        (Collection<BundleRevision>) arg2);
+                    return null;
+                case INVOKE_RESOLVER_HOOK_SINGLETON:
+                    ((org.osgi.framework.hooks.resolver.ResolverHook) arg1)
+                        .filterSingletonCollisions(
+                            (BundleCapability) arg2,
+                            (Collection<BundleCapability>) arg3);
+                    return null;
+                case INVOKE_RESOLVER_HOOK_MATCHES:
+                    ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).filterMatches(
+                        (BundleRequirement) arg2,
+                        (Collection<BundleCapability>) arg3);
+                    return null;
+                case INVOKE_RESOLVER_HOOK_END:
+                    ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).end();
+                    return null;*/
+            }
+
+            return null;
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/StringComparator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/StringComparator.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/StringComparator.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/StringComparator.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util;
+
+import java.util.Comparator;
+
+public class StringComparator implements Comparator
+{
+    private final boolean m_isCaseSensitive;
+
+    public StringComparator(boolean b)
+    {
+        m_isCaseSensitive = b;
+    }
+
+    public int compare(Object o1, Object o2)
+    {
+        if (m_isCaseSensitive)
+        {
+            return o1.toString().compareTo(o2.toString());
+        }
+        else
+        {
+            return o1.toString().compareToIgnoreCase(o2.toString());
+        }
+    }
+
+    public boolean isCaseSensitive()
+    {
+        return m_isCaseSensitive;
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/Util.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/Util.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/Util.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/Util.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,649 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util;
+
+import java.io.*;
+import java.net.URL;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.capabilityset.CapabilitySet;
+import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+import org.apache.felix.framework.wiring.BundleRequirementImpl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+public class Util
+{
+    /**
+     * The default name used for the default configuration properties file.
+    **/
+    private static final String DEFAULT_PROPERTIES_FILE = "default.properties";
+
+    public static String getDefaultProperty(Logger logger, String name)
+    {
+        String value = null;
+
+        URL propURL = Util.class.getClassLoader().getResource(DEFAULT_PROPERTIES_FILE);
+        if (propURL != null)
+        {
+            InputStream is = null;
+            try
+            {
+                // Load properties from URL.
+                is = propURL.openConnection().getInputStream();
+                Properties props = new Properties();
+                props.load(is);
+                is.close();
+                // Perform variable substitution for property.
+                value = props.getProperty(name);
+                value = (value != null)
+                    ? Util.substVars(value, name, null, props)
+                    : null;
+            }
+            catch (Exception ex)
+            {
+                // Try to close input stream if we have one.
+                try
+                {
+                    if (is != null) is.close();
+                }
+                catch (IOException ex2)
+                {
+                    // Nothing we can do.
+                }
+
+                logger.log(
+                    Logger.LOG_ERROR, "Unable to load any configuration properties.", ex);
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Converts a revision identifier to a bundle identifier. Revision IDs
+     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
+     * method returns only the portion corresponding to the bundle ID.
+    **/
+    public static long getBundleIdFromRevisionId(String id)
+    {
+        try
+        {
+            String bundleId = (id.indexOf('.') >= 0)
+                ? id.substring(0, id.indexOf('.')) : id;
+            return Long.parseLong(bundleId);
+        }
+        catch (NumberFormatException ex)
+        {
+            return -1;
+        }
+    }
+
+    /**
+     * Converts a module identifier to a bundle identifier. Module IDs
+     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
+     * method returns only the portion corresponding to the revision.
+    **/
+    public static int getModuleRevisionFromModuleId(String id)
+    {
+        try
+        {
+            int index = id.indexOf('.');
+            if (index >= 0)
+            {
+                return Integer.parseInt(id.substring(index + 1));
+            }
+        }
+        catch (NumberFormatException ex)
+        {
+        }
+        return -1;
+    }
+
+    public static String getClassName(String className)
+    {
+        if (className == null)
+        {
+            className = "";
+        }
+        return (className.lastIndexOf('.') < 0)
+            ? "" : className.substring(className.lastIndexOf('.') + 1);
+    }
+
+    public static String getClassPackage(String className)
+    {
+        if (className == null)
+        {
+            className = "";
+        }
+        return (className.lastIndexOf('.') < 0)
+            ? "" : className.substring(0, className.lastIndexOf('.'));
+    }
+
+    public static String getResourcePackage(String resource)
+    {
+        if (resource == null)
+        {
+            resource = "";
+        }
+        // NOTE: The package of a resource is tricky to determine since
+        // resources do not follow the same naming conventions as classes.
+        // This code is pessimistic and assumes that the package of a
+        // resource is everything up to the last '/' character. By making
+        // this choice, it will not be possible to load resources from
+        // imports using relative resource names. For example, if a
+        // bundle exports "foo" and an importer of "foo" tries to load
+        // "/foo/bar/myresource.txt", this will not be found in the exporter
+        // because the following algorithm assumes the package name is
+        // "foo.bar", not just "foo". This only affects imported resources,
+        // local resources will work as expected.
+        String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource;
+        pkgName = (pkgName.lastIndexOf('/') < 0)
+            ? "" : pkgName.substring(0, pkgName.lastIndexOf('/'));
+        pkgName = pkgName.replace('/', '.');
+        return pkgName;
+    }
+
+    /**
+     * <p>
+     * This is a simple utility class that attempts to load the named
+     * class using the class loader of the supplied class or
+     * the class loader of one of its super classes or their implemented
+     * interfaces. This is necessary during service registration to test
+     * whether a given service object implements its declared service
+     * interfaces.
+     * </p>
+     * <p>
+     * To perform this test, the framework must try to load
+     * the classes associated with the declared service interfaces, so
+     * it must choose a class loader. The class loader of the registering
+     * bundle cannot be used, since this disallows third parties to
+     * register service on behalf of another bundle. Consequently, the
+     * class loader of the service object must be used. However, this is
+     * also not sufficient since the class loader of the service object
+     * may not have direct access to the class in question.
+     * </p>
+     * <p>
+     * The service object's class loader may not have direct access to
+     * its service interface if it extends a super class from another
+     * bundle which implements the service interface from an imported
+     * bundle or if it implements an extension of the service interface
+     * from another bundle which imports the base interface from another
+     * bundle. In these cases, the service object's class loader only has
+     * access to the super class's class or the extended service interface,
+     * respectively, but not to the actual service interface.
+     * </p>
+     * <p>
+     * Thus, it is necessary to not only try to load the service interface
+     * class from the service object's class loader, but from the class
+     * loaders of any interfaces it implements and the class loaders of
+     * all super classes.
+     * </p>
+     * @param svcObj the class that is the root of the search.
+     * @param name the name of the class to load.
+     * @return the loaded class or <tt>null</tt> if it could not be
+     *         loaded.
+    **/
+    public static Class loadClassUsingClass(Class clazz, String name, SecureAction action)
+    {
+        Class loadedClass = null;
+
+        while (clazz != null)
+        {
+            // Get the class loader of the current class object.
+            ClassLoader loader = action.getClassLoader(clazz);
+            // A null class loader represents the system class loader.
+            loader = (loader == null) ? action.getSystemClassLoader() : loader;
+            try
+            {
+                return loader.loadClass(name);
+            }
+            catch (ClassNotFoundException ex)
+            {
+                // Ignore and try interface class loaders.
+            }
+
+            // Try to see if we can load the class from
+            // one of the class's implemented interface
+            // class loaders.
+            Class[] ifcs = clazz.getInterfaces();
+            for (int i = 0; i < ifcs.length; i++)
+            {
+                loadedClass = loadClassUsingClass(ifcs[i], name, action);
+                if (loadedClass != null)
+                {
+                    return loadedClass;
+                }
+            }
+
+            // Try to see if we can load the class from
+            // the super class class loader.
+            clazz = clazz.getSuperclass();
+        }
+
+        return null;
+    }
+
+    /**
+     * This method determines if the requesting bundle is able to cast
+     * the specified service reference based on class visibility rules
+     * of the underlying modules.
+     * @param requester The bundle requesting the service.
+     * @param ref The service in question.
+     * @return <tt>true</tt> if the requesting bundle is able to case
+     *         the service object to a known type.
+    **/
+    public static boolean isServiceAssignable(Bundle requester, ServiceReference ref)
+    {
+        // Boolean flag.
+        boolean allow = true;
+        // Get the service's objectClass property.
+        String[] objectClass = (String[]) ref.getProperty(FelixConstants.OBJECTCLASS);
+
+        // The the service reference is not assignable when the requesting
+        // bundle is wired to a different version of the service object.
+        // NOTE: We are pessimistic here, if any class in the service's
+        // objectClass is not usable by the requesting bundle, then we
+        // disallow the service reference.
+        for (int classIdx = 0; (allow) && (classIdx < objectClass.length); classIdx++)
+        {
+            if (!ref.isAssignableTo(requester, objectClass[classIdx]))
+            {
+                allow = false;
+            }
+        }
+        return allow;
+    }
+
+    public static BundleCapability getSatisfyingCapability(
+        BundleRevision br, BundleRequirementImpl req)
+    {
+        List<BundleCapability> caps = (br.getWiring() != null)
+            ? br.getWiring().getCapabilities(null)
+            : br.getDeclaredCapabilities(null);
+        if (caps != null)
+        {
+            for (BundleCapability cap : caps)
+            {
+                if (cap.getNamespace().equals(req.getNamespace())
+                    && CapabilitySet.matches((BundleCapabilityImpl) cap, req.getFilter()))
+                {
+                    return cap;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns all the capabilities from a module that has a specified namespace.
+     *
+     * @param br    module providing capabilities
+     * @param namespace capability namespace
+     * @return array of matching capabilities or empty if none found
+     */
+    public static List<BundleCapability> getCapabilityByNamespace(
+        BundleRevision br, String namespace)
+    {
+        final List<BundleCapability> matching = new ArrayList();
+        final List<BundleCapability> caps = (br.getWiring() != null)
+            ? br.getWiring().getCapabilities(null)
+            : br.getDeclaredCapabilities(null);
+        if (caps != null)
+        {
+            for (BundleCapability cap : caps)
+            {
+                if (cap.getNamespace().equals(namespace))
+                {
+                    matching.add(cap);
+                }
+            }
+        }
+        return matching;
+    }
+
+    public static List<BundleRequirement> getDynamicRequirements(
+        List<BundleRequirement> reqs)
+    {
+        List<BundleRequirement> result = new ArrayList<BundleRequirement>();
+        if (reqs != null)
+        {
+            for (BundleRequirement req : reqs)
+            {
+                String resolution = req.getDirectives().get(Constants.RESOLUTION_DIRECTIVE);
+                if ((resolution != null) && resolution.equals("dynamic"))
+                {
+                    result.add(req);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static BundleWire getWire(BundleRevision br, String name)
+    {
+        if (br.getWiring() != null)
+        {
+            List<BundleWire> wires = br.getWiring().getRequiredWires(null);
+            if (wires != null)
+            {
+                for (BundleWire w : wires)
+                {
+                    if (w.getCapability().getNamespace()
+                            .equals(BundleRevision.PACKAGE_NAMESPACE) &&
+                        w.getCapability().getAttributes()
+                            .get(BundleRevision.PACKAGE_NAMESPACE).equals(name))
+                    {
+                        return w;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+        0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
+        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+        0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31,
+        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f };
+
+    private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,
+        -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
+        -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
+        30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+        48, 49, 50, 51, -1, -1, -1, -1, -1 };
+
+    public static String base64Encode(String s) throws IOException
+    {
+        return encode(s.getBytes(), 0);
+    }
+
+    /**
+     * Encode a raw byte array to a Base64 String.
+     *
+     * @param in Byte array to encode.
+     * @param len Length of Base64 lines. 0 means no line breaks.
+    **/
+    public static String encode(byte[] in, int len) throws IOException
+    {
+        ByteArrayOutputStream baos = null;
+        ByteArrayInputStream bais = null;
+        try
+        {
+            baos = new ByteArrayOutputStream();
+            bais = new ByteArrayInputStream(in);
+            encode(bais, baos, len);
+            // ASCII byte array to String
+            return (new String(baos.toByteArray()));
+        }
+        finally
+        {
+            if (baos != null)
+            {
+                baos.close();
+            }
+            if (bais != null)
+            {
+                bais.close();
+            }
+        }
+    }
+
+    public static void encode(InputStream in, OutputStream out, int len)
+        throws IOException
+    {
+
+        // Check that length is a multiple of 4 bytes
+        if (len % 4 != 0)
+        {
+            throw new IllegalArgumentException("Length must be a multiple of 4");
+        }
+
+        // Read input stream until end of file
+        int bits = 0;
+        int nbits = 0;
+        int nbytes = 0;
+        int b;
+
+        while ((b = in.read()) != -1)
+        {
+            bits = (bits << 8) | b;
+            nbits += 8;
+            while (nbits >= 6)
+            {
+                nbits -= 6;
+                out.write(encTab[0x3f & (bits >> nbits)]);
+                nbytes++;
+                // New line
+                if (len != 0 && nbytes >= len)
+                {
+                    out.write(0x0d);
+                    out.write(0x0a);
+                    nbytes -= len;
+                }
+            }
+        }
+
+        switch (nbits)
+        {
+            case 2:
+                out.write(encTab[0x3f & (bits << 4)]);
+                out.write(0x3d); // 0x3d = '='
+                out.write(0x3d);
+                break;
+            case 4:
+                out.write(encTab[0x3f & (bits << 2)]);
+                out.write(0x3d);
+                break;
+        }
+
+        if (len != 0)
+        {
+            if (nbytes != 0)
+            {
+                out.write(0x0d);
+                out.write(0x0a);
+            }
+            out.write(0x0d);
+            out.write(0x0a);
+        }
+    }
+
+
+    private static final String DELIM_START = "${";
+    private static final String DELIM_STOP  = "}";
+
+    /**
+     * <p>
+     * This method performs property variable substitution on the
+     * specified value. If the specified value contains the syntax
+     * <tt>${&lt;prop-name&gt;}</tt>, where <tt>&lt;prop-name&gt;</tt>
+     * refers to either a configuration property or a system property,
+     * then the corresponding property value is substituted for the variable
+     * placeholder. Multiple variable placeholders may exist in the
+     * specified value as well as nested variable placeholders, which
+     * are substituted from inner most to outer most. Configuration
+     * properties override system properties.
+     * </p>
+     * @param val The string on which to perform property substitution.
+     * @param currentKey The key of the property being evaluated used to
+     *        detect cycles.
+     * @param cycleMap Map of variable references used to detect nested cycles.
+     * @param configProps Set of configuration properties.
+     * @return The value of the specified string after system property substitution.
+     * @throws IllegalArgumentException If there was a syntax error in the
+     *         property placeholder syntax or a recursive variable reference.
+    **/
+    public static String substVars(String val, String currentKey,
+        Map cycleMap, Properties configProps)
+        throws IllegalArgumentException
+    {
+        // If there is currently no cycle map, then create
+        // one for detecting cycles for this invocation.
+        if (cycleMap == null)
+        {
+            cycleMap = new HashMap();
+        }
+
+        // Put the current key in the cycle map.
+        cycleMap.put(currentKey, currentKey);
+
+        // Assume we have a value that is something like:
+        // "leading ${foo.${bar}} middle ${baz} trailing"
+
+        // Find the first ending '}' variable delimiter, which
+        // will correspond to the first deepest nested variable
+        // placeholder.
+        int stopDelim = -1;
+        int startDelim = -1;
+
+        do
+        {
+            stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1);
+            // If there is no stopping delimiter, then just return
+            // the value since there is no variable declared.
+            if (stopDelim < 0)
+            {
+                return val;
+            }
+            // Try to find the matching start delimiter by
+            // looping until we find a start delimiter that is
+            // greater than the stop delimiter we have found.
+            startDelim = val.indexOf(DELIM_START);
+            // If there is no starting delimiter, then just return
+            // the value since there is no variable declared.
+            if (startDelim < 0)
+            {
+                return val;
+            }
+            while (stopDelim >= 0)
+            {
+                int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
+                if ((idx < 0) || (idx > stopDelim))
+                {
+                    break;
+                }
+                else if (idx < stopDelim)
+                {
+                    startDelim = idx;
+                }
+            }
+        }
+        while ((startDelim > stopDelim) && (stopDelim >= 0));
+
+        // At this point, we have found a variable placeholder so
+        // we must perform a variable substitution on it.
+        // Using the start and stop delimiter indices, extract
+        // the first, deepest nested variable placeholder.
+        String variable =
+            val.substring(startDelim + DELIM_START.length(), stopDelim);
+
+        // Verify that this is not a recursive variable reference.
+        if (cycleMap.get(variable) != null)
+        {
+            throw new IllegalArgumentException(
+                "recursive variable reference: " + variable);
+        }
+
+        // Get the value of the deepest nested variable placeholder.
+        // Try to configuration properties first.
+        String substValue = (configProps != null)
+            ? configProps.getProperty(variable, null)
+            : null;
+        if (substValue == null)
+        {
+            // Ignore unknown property values.
+            substValue = System.getProperty(variable, "");
+        }
+
+        // Remove the found variable from the cycle map, since
+        // it may appear more than once in the value and we don't
+        // want such situations to appear as a recursive reference.
+        cycleMap.remove(variable);
+
+        // Append the leading characters, the substituted value of
+        // the variable, and the trailing characters to get the new
+        // value.
+        val = val.substring(0, startDelim)
+            + substValue
+            + val.substring(stopDelim + DELIM_STOP.length(), val.length());
+
+        // Now perform substitution again, since there could still
+        // be substitutions to make.
+        val = substVars(val, currentKey, cycleMap, configProps);
+
+        // Return the value.
+        return val;
+    }
+
+    /**
+     * Checks if the provided module definition declares a fragment host.
+     *
+     * @param module the module to check
+     * @return <code>true</code> if the module declares a fragment host, <code>false</code>
+     *      otherwise.
+     */
+    public static boolean isFragment(BundleRevision revision)
+    {
+        return ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) > 0);
+    }
+
+    public static List<BundleRevision> getFragments(BundleWiring wiring)
+    {
+        List<BundleRevision> fragments = Collections.EMPTY_LIST;
+        if (wiring != null)
+        {
+            List<BundleWire> wires = wiring.getProvidedWires(null);
+            if (wires != null)
+            {
+                for (BundleWire w : wires)
+                {
+                    if (w.getCapability().getNamespace()
+                        .equals(BundleRevision.HOST_NAMESPACE))
+                    {
+                        // Create array list if needed.
+                        if (fragments.isEmpty())
+                        {
+                            fragments = new ArrayList<BundleRevision>();
+                        }
+                        fragments.add(w.getRequirerWiring().getRevision());
+                    }
+                }
+            }
+        }
+        return fragments;
+    }
+}
\ No newline at end of file