You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by jw...@apache.org on 2015/09/02 17:26:45 UTC

svn commit: r1700842 [2/3] - in /aries/trunk/subsystem: subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-itests/src/test/java/org/apache/aries/s...

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SecureAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SecureAction.java?rev=1700842&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SecureAction.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SecureAction.java Wed Sep  2 15:26:45 2015
@@ -0,0 +1,1815 @@
+/*
+ * 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.aries.subsystem.core.capabilityset;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Policy;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.jar.JarFile;
+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, ClassLoader classloader) throws ClassNotFoundException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.FOR_NAME_ACTION, name, classloader);
+                return (Class) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof ClassNotFoundException)
+                {
+                    throw (ClassNotFoundException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else if (classloader != null)
+        {
+            return Class.forName(name, true, classloader);
+        }
+        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 void deleteFileOnExit(File file)
+        throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.DELETE_FILEONEXIT_ACTION, file);
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            file.deleteOnExit();
+        }
+    }
+
+    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 JarFile openJarFile(File file) throws IOException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.OPEN_JARFILE_ACTION, file);
+                return (JarFile) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof IOException)
+                {
+                    throw (IOException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new JarFile(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 invokeBundleCollisionHook(
+        org.osgi.framework.hooks.bundle.CollisionHook ch, int operationType,
+        Bundle targetBundle, Collection<Bundle> collisionCandidates)
+        throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_BUNDLE_COLLISION_HOOK, ch, operationType, targetBundle, collisionCandidates);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            ch.filterCollisions(operationType, targetBundle, collisionCandidates);
+        }
+    }
+
+    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, event, 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, event, 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_FIND_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, event, 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();
+        }
+    }
+
+    public void invokeWovenClassListener(
+            org.osgi.framework.hooks.weaving.WovenClassListener wcl,
+            org.osgi.framework.hooks.weaving.WovenClass wc)
+            throws Exception
+    {
+        if (System.getSecurityManager() != null)
+        {
+            Actions actions = (Actions) m_actions.get();
+            actions.set(Actions.INVOKE_WOVEN_CLASS_LISTENER, wcl, wc);
+            try
+            {
+                AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException e)
+            {
+                throw e.getException();
+            }
+        }
+        else
+        {
+            wcl.modified(wc);
+        }
+    }
+
+    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;
+        public static final int INVOKE_BUNDLE_COLLISION_HOOK = 53;
+        public static final int OPEN_JARFILE_ACTION = 54;
+        public static final int DELETE_FILEONEXIT_ACTION = 55;
+        public static final int INVOKE_WOVEN_CLASS_LISTENER = 56;
+
+        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 (arg2 == null) ? Class.forName((String) arg1) : Class.forName((String) arg1, true,
+                        (ClassLoader) arg2);
+                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;
+                case INVOKE_BUNDLE_COLLISION_HOOK:
+                    ((org.osgi.framework.hooks.bundle.CollisionHook) arg1).filterCollisions((Integer) arg2,
+                        (Bundle) arg3, (Collection<Bundle>) arg4);
+                    return null;
+                case OPEN_JARFILE_ACTION:
+                    return new JarFile((File) arg1);
+                case DELETE_FILEONEXIT_ACTION:
+                    ((File) arg1).deleteOnExit();
+                    return null;
+                case INVOKE_WOVEN_CLASS_LISTENER:
+                    ((org.osgi.framework.hooks.weaving.WovenClassListener) arg1).modified(
+                        (org.osgi.framework.hooks.weaving.WovenClass) arg2);
+                    return null;
+            }
+
+            return null;
+        }
+    }
+}

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SimpleFilter.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SimpleFilter.java?rev=1700842&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SimpleFilter.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/SimpleFilter.java Wed Sep  2 15:26:45 2015
@@ -0,0 +1,651 @@
+/*
+ * 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.aries.subsystem.core.capabilityset;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.osgi.framework.VersionRange;
+
+public class SimpleFilter
+{
+    public static final int MATCH_ALL = 0;
+    public static final int AND = 1;
+    public static final int OR = 2;
+    public static final int NOT = 3;
+    public static final int EQ = 4;
+    public static final int LTE = 5;
+    public static final int GTE = 6;
+    public static final int SUBSTRING = 7;
+    public static final int PRESENT = 8;
+    public static final int APPROX = 9;
+
+    private final String m_name;
+    private final Object m_value;
+    private final int m_op;
+
+    public SimpleFilter(String attr, Object value, int op)
+    {
+        m_name = attr;
+        m_value = value;
+        m_op = op;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public Object getValue()
+    {
+        return m_value;
+    }
+
+    public int getOperation()
+    {
+        return m_op;
+    }
+
+    public String toString()
+    {
+        String s = null;
+        switch (m_op)
+        {
+            case AND:
+                s = "(&" + toString((List) m_value) + ")";
+                break;
+            case OR:
+                s = "(|" + toString((List) m_value) + ")";
+                break;
+            case NOT:
+                s = "(!" + toString((List) m_value) + ")";
+                break;
+            case EQ:
+                s = "(" + m_name + "=" + toEncodedString(m_value) + ")";
+                break;
+            case LTE:
+                s = "(" + m_name + "<=" + toEncodedString(m_value) + ")";
+                break;
+            case GTE:
+                s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
+                break;
+            case SUBSTRING:
+                s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
+                break;
+            case PRESENT:
+                s = "(" + m_name + "=*)";
+                break;
+            case APPROX:
+                s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
+                break;
+            case MATCH_ALL:
+                s = "(*)";
+                break;
+        }
+        return s;
+    }
+
+    private static String toString(List list)
+    {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < list.size(); i++)
+        {
+            sb.append(list.get(i).toString());
+        }
+        return sb.toString();
+    }
+
+    private static String toDecodedString(String s, int startIdx, int endIdx)
+    {
+        StringBuffer sb = new StringBuffer(endIdx - startIdx);
+        boolean escaped = false;
+        for (int i = 0; i < (endIdx - startIdx); i++)
+        {
+            char c = s.charAt(startIdx + i);
+            if (!escaped && (c == '\\'))
+            {
+                escaped = true;
+            }
+            else
+            {
+                escaped = false;
+                sb.append(c);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    private static String toEncodedString(Object o)
+    {
+        if (o instanceof String)
+        {
+            String s = (String) o;
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < s.length(); i++)
+            {
+                char c = s.charAt(i);
+                if ((c == '\\') || (c == '(') || (c == ')') || (c == '*'))
+                {
+                    sb.append('\\');
+                }
+                sb.append(c);
+            }
+
+            o = sb.toString();
+        }
+
+        return o.toString();
+    }
+
+    public static SimpleFilter parse(String filter)
+    {
+        int idx = skipWhitespace(filter, 0);
+
+        if ((filter == null) || (filter.length() == 0) || (idx >= filter.length()))
+        {
+            throw new IllegalArgumentException("Null or empty filter.");
+        }
+        else if (filter.charAt(idx) != '(')
+        {
+            throw new IllegalArgumentException("Missing opening parenthesis: " + filter);
+        }
+
+        SimpleFilter sf = null;
+        List stack = new ArrayList();
+        boolean isEscaped = false;
+        while (idx < filter.length())
+        {
+            if (sf != null)
+            {
+                throw new IllegalArgumentException(
+                    "Only one top-level operation allowed: " + filter);
+            }
+
+            if (!isEscaped && (filter.charAt(idx) == '('))
+            {
+                // Skip paren and following whitespace.
+                idx = skipWhitespace(filter, idx + 1);
+
+                if (filter.charAt(idx) == '&')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.AND));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else if (filter.charAt(idx) == '|')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.OR));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else if (filter.charAt(idx) == '!')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else
+                {
+                    stack.add(0, new Integer(idx));
+                }
+            }
+            else if (!isEscaped && (filter.charAt(idx) == ')'))
+            {
+                Object top = stack.remove(0);
+                if (top instanceof SimpleFilter)
+                {
+                    if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+                    {
+                        ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
+                    }
+                    else
+                    {
+                        sf = (SimpleFilter) top;
+                    }
+                }
+                else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+                {
+                    ((List) ((SimpleFilter) stack.get(0)).m_value).add(
+                        SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx));
+                }
+                else
+                {
+                    sf = SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx);
+                }
+            }
+            else if (!isEscaped && (filter.charAt(idx) == '\\'))
+            {
+                isEscaped = true;
+            }
+            else
+            {
+                isEscaped = false;
+            }
+
+            idx = skipWhitespace(filter, idx + 1);
+        }
+
+        if (sf == null)
+        {
+            throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
+        }
+
+        return sf;
+    }
+
+    private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
+    {
+        final String opChars = "=<>~";
+
+        // Determine the ending index of the attribute name.
+        int attrEndIdx = startIdx;
+        for (int i = 0; i < (endIdx - startIdx); i++)
+        {
+            char c = filter.charAt(startIdx + i);
+            if (opChars.indexOf(c) >= 0)
+            {
+                break;
+            }
+            else if (!Character.isWhitespace(c))
+            {
+                attrEndIdx = startIdx + i + 1;
+            }
+        }
+        if (attrEndIdx == startIdx)
+        {
+            throw new IllegalArgumentException(
+                "Missing attribute name: " + filter.substring(startIdx, endIdx));
+        }
+        String attr = filter.substring(startIdx, attrEndIdx);
+
+        // Skip the attribute name and any following whitespace.
+        startIdx = skipWhitespace(filter, attrEndIdx);
+
+        // Determine the operator type.
+        int op = -1;
+        switch (filter.charAt(startIdx))
+        {
+            case '=':
+                op = EQ;
+                startIdx++;
+                break;
+            case '<':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                        "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = LTE;
+                startIdx += 2;
+                break;
+            case '>':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                        "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = GTE;
+                startIdx += 2;
+                break;
+            case '~':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                        "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = APPROX;
+                startIdx += 2;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                    "Unknown operator: " + filter.substring(startIdx, endIdx));
+        }
+
+        // Parse value.
+        Object value = toDecodedString(filter, startIdx, endIdx);
+
+        // Check if the equality comparison is actually a substring
+        // or present operation.
+        if (op == EQ)
+        {
+            String valueStr = filter.substring(startIdx, endIdx);
+            List<String> values = parseSubstring(valueStr);
+            if ((values.size() == 2)
+                && (values.get(0).length() == 0)
+                && (values.get(1).length() == 0))
+            {
+                op = PRESENT;
+            }
+            else if (values.size() > 1)
+            {
+                op = SUBSTRING;
+                value = values;
+            }
+        }
+
+        return new SimpleFilter(attr, value, op);
+    }
+
+    public static List<String> parseSubstring(String value)
+    {
+        List<String> pieces = new ArrayList();
+        StringBuffer ss = new StringBuffer();
+        // int kind = SIMPLE; // assume until proven otherwise
+        boolean wasStar = false; // indicates last piece was a star
+        boolean leftstar = false; // track if the initial piece is a star
+        boolean rightstar = false; // track if the final piece is a star
+
+        int idx = 0;
+
+        // We assume (sub)strings can contain leading and trailing blanks
+        boolean escaped = false;
+loop:   for (;;)
+        {
+            if (idx >= value.length())
+            {
+                if (wasStar)
+                {
+                    // insert last piece as "" to handle trailing star
+                    rightstar = true;
+                }
+                else
+                {
+                    pieces.add(ss.toString());
+                    // accumulate the last piece
+                    // note that in the case of
+                    // (cn=); this might be
+                    // the string "" (!=null)
+                }
+                ss.setLength(0);
+                break loop;
+            }
+
+            // Read the next character and account for escapes.
+            char c = value.charAt(idx++);
+            if (!escaped && (c == '*'))
+            {
+                // If we have successive '*' characters, then we can
+                // effectively collapse them by ignoring succeeding ones.
+                if (!wasStar)
+                {
+                    if (ss.length() > 0)
+                    {
+                        pieces.add(ss.toString()); // accumulate the pieces
+                        // between '*' occurrences
+                    }
+                    ss.setLength(0);
+                    // if this is a leading star, then track it
+                    if (pieces.isEmpty())
+                    {
+                        leftstar = true;
+                    }
+                    wasStar = true;
+                }
+            }
+            else if (!escaped && (c == '\\'))
+            {
+                escaped = true;
+            }
+            else
+            {
+                escaped = false;
+                wasStar = false;
+                ss.append(c);
+            }
+        }
+        if (leftstar || rightstar || pieces.size() > 1)
+        {
+            // insert leading and/or trailing "" to anchor ends
+            if (rightstar)
+            {
+                pieces.add("");
+            }
+            if (leftstar)
+            {
+                pieces.add(0, "");
+            }
+        }
+        return pieces;
+    }
+
+    public static String unparseSubstring(List<String> pieces)
+    {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < pieces.size(); i++)
+        {
+            if (i > 0)
+            {
+                sb.append("*");
+            }
+            sb.append(toEncodedString(pieces.get(i)));
+        }
+        return sb.toString();
+    }
+
+    public static boolean compareSubstring(List<String> pieces, String s)
+    {
+        // Walk the pieces to match the string
+        // There are implicit stars between each piece,
+        // and the first and last pieces might be "" to anchor the match.
+        // assert (pieces.length > 1)
+        // minimal case is <string>*<string>
+
+        boolean result = true;
+        int len = pieces.size();
+
+        // Special case, if there is only one piece, then
+        // we must perform an equality test.
+        if (len == 1)
+        {
+            return s.equals(pieces.get(0));
+        }
+
+        // Otherwise, check whether the pieces match
+        // the specified string.
+
+        int index = 0;
+
+loop:   for (int i = 0; i < len; i++)
+        {
+            String piece = pieces.get(i);
+
+            // If this is the first piece, then make sure the
+            // string starts with it.
+            if (i == 0)
+            {
+                if (!s.startsWith(piece))
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+
+            // If this is the last piece, then make sure the
+            // string ends with it.
+            if (i == (len - 1))
+            {
+                if (s.endsWith(piece) && (s.length() >= (index + piece.length())))
+                {
+                    result = true;
+                }
+                else
+                {
+                    result = false;
+                }
+                break loop;
+            }
+
+            // If this is neither the first or last piece, then
+            // make sure the string contains it.
+            if ((i > 0) && (i < (len - 1)))
+            {
+                index = s.indexOf(piece, index);
+                if (index < 0)
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+
+            // Move string index beyond the matching piece.
+            index += piece.length();
+        }
+
+        return result;
+    }
+
+    private static int skipWhitespace(String s, int startIdx)
+    {
+        int len = s.length();
+        while ((startIdx < len) && Character.isWhitespace(s.charAt(startIdx)))
+        {
+            startIdx++;
+        }
+        return startIdx;
+    }
+
+    /**
+     * Converts a attribute map to a filter. The filter is created by iterating
+     * over the map's entry set. If ordering of attributes is important (e.g.,
+     * for hitting attribute indices), then the map's entry set should iterate
+     * in the desired order. Equality testing is assumed for all attribute types
+     * other than version ranges, which are handled appropriated. If the attribute
+     * map is empty, then a filter that matches anything is returned.
+     * @param attrs Map of attributes to convert to a filter.
+     * @return A filter corresponding to the attributes.
+     */
+    public static SimpleFilter convert(Map<String, Object> attrs)
+    {
+        // Rather than building a filter string to be parsed into a SimpleFilter,
+        // we will just create the parsed SimpleFilter directly.
+
+        List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
+
+        for (Entry<String, Object> entry : attrs.entrySet())
+        {
+            if (entry.getValue() instanceof VersionRange)
+            {
+                VersionRange vr = (VersionRange) entry.getValue();
+                if (vr.getLeftType() == VersionRange.RIGHT_OPEN)
+                {
+                    filters.add(
+                        new SimpleFilter(
+                            entry.getKey(),
+                            vr.getLeft().toString(),
+                            SimpleFilter.GTE));
+                }
+                else
+                {
+                    SimpleFilter not =
+                        new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+                    ((List) not.getValue()).add(
+                        new SimpleFilter(
+                            entry.getKey(),
+                            vr.getLeft().toString(),
+                            SimpleFilter.LTE));
+                    filters.add(not);
+                }
+
+                if (vr.getRight() != null)
+                {
+                    if (vr.getRightType() == VersionRange.RIGHT_OPEN)
+                    {
+                        filters.add(
+                            new SimpleFilter(
+                                entry.getKey(),
+                                vr.getRight().toString(),
+                                SimpleFilter.LTE));
+                    }
+                    else
+                    {
+                        SimpleFilter not =
+                            new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+                        ((List) not.getValue()).add(
+                            new SimpleFilter(
+                                entry.getKey(),
+                                vr.getRight().toString(),
+                                SimpleFilter.GTE));
+                        filters.add(not);
+                    }
+                }
+            }
+            else
+            {
+                List<String> values = SimpleFilter.parseSubstring(entry.getValue().toString());
+                if (values.size() > 1)
+                {
+                    filters.add(
+                        new SimpleFilter(
+                            entry.getKey(),
+                            values,
+                            SimpleFilter.SUBSTRING));
+                }
+                else
+                {
+                    filters.add(
+                        new SimpleFilter(
+                            entry.getKey(),
+                            values.get(0),
+                            SimpleFilter.EQ));
+                }
+            }
+        }
+
+        SimpleFilter sf = null;
+
+        if (filters.size() == 1)
+        {
+            sf = filters.get(0);
+        }
+        else if (attrs.size() > 1)
+        {
+            sf = new SimpleFilter(null, filters, SimpleFilter.AND);
+        }
+        else if (filters.isEmpty())
+        {
+            sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+        }
+
+        return sf;
+    }
+}
\ No newline at end of file

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/StringComparator.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/StringComparator.java?rev=1700842&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/StringComparator.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/capabilityset/StringComparator.java Wed Sep  2 15:26:45 2015
@@ -0,0 +1,73 @@
+/*
+ * 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.aries.subsystem.core.capabilityset;
+
+import java.util.Comparator;
+
+public class StringComparator implements Comparator<String>
+{
+
+    public static final StringComparator COMPARATOR = new StringComparator();
+
+    public int compare(String s1, String s2)
+    {
+        int n1 = s1.length();
+        int n2 = s2.length();
+        int min = n1 < n2 ? n1 : n2;
+        for ( int i = 0; i < min; i++ )
+        {
+            char c1 = s1.charAt( i );
+            char c2 = s2.charAt( i );
+            if ( c1 != c2 )
+            {
+                // Fast check for simple ascii codes
+                if ( c1 <= 128 && c2 <= 128 )
+                {
+                    c1 = toLowerCaseFast(c1);
+                    c2 = toLowerCaseFast(c2);
+                    if ( c1 != c2 )
+                    {
+                        return c1 - c2;
+                    }
+                }
+                else
+                {
+                    c1 = Character.toUpperCase( c1 );
+                    c2 = Character.toUpperCase( c2 );
+                    if ( c1 != c2 )
+                    {
+                        c1 = Character.toLowerCase( c1 );
+                        c2 = Character.toLowerCase( c2 );
+                        if ( c1 != c2 )
+                        {
+                            // No overflow because of numeric promotion
+                            return c1 - c2;
+                        }
+                    }
+                }
+            }
+        }
+        return n1 - n2;
+    }
+
+    private static char toLowerCaseFast( char ch )
+    {
+        return ( ch >= 'A' && ch <= 'Z' ) ? ( char ) ( ch + 'a' - 'A' ) : ch;
+    }
+}
\ No newline at end of file