Add support for the 4.2.0 security specifications. This includes implementations of the access flag and various other changes (FELIX-1904, FELIX-22).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@897721 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework.security/pom.xml b/framework.security/pom.xml
index c80eefb..81a7df2 100644
--- a/framework.security/pom.xml
+++ b/framework.security/pom.xml
@@ -34,7 +34,7 @@
      <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
-      <version>4.1.0</version>
+      <version>4.2.0</version>
     </dependency>
     <dependency>
       <groupId>${pom.groupId}</groupId>
diff --git a/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java b/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
index f33b6fb..bc4a0bd 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
@@ -20,12 +20,9 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
 import java.util.StringTokenizer;
-import java.util.Map.Entry;
 
+import org.apache.felix.framework.ext.SecurityProvider;
 import org.apache.felix.framework.security.SecurityConstants;
 import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
 import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
@@ -33,81 +30,72 @@
 import org.apache.felix.framework.security.util.LocalPermissions;
 import org.apache.felix.framework.security.util.Permissions;
 import org.apache.felix.framework.security.util.PropertiesCache;
-import org.apache.felix.framework.security.verifier.BundleDNParser;
 import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
 import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
 import org.osgi.service.permissionadmin.PermissionAdmin;
 
 /**
- * <p>This Felix specific activator installs a security provider with the Felix
+ * <p>
+ * This Felix specific activator installs a security provider with the Felix
  * framework. The security settings can be changed via the
- * {@link PermissionAdmin} and/or the
- * {@link ConditionalPermissionAdmin} services that may be published by
- * this class.
+ * {@link PermissionAdmin} and/or the {@link ConditionalPermissionAdmin}
+ * services that may be published by this class.
  * </p>
  * <p>
- * Permission informations as well as caching data will be stored in several 
- * files in a directory called <tt>security</tt> obtained by a call to 
+ * Permission informations as well as caching data will be stored in several
+ * files in a directory called <tt>security</tt> obtained by a call to
  * {@link BundleContext#getDataFile(String))}.
  * </p>
  * <p>
  * The following properties are recognized:
  * <p>
- * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not 
- * (<tt>true</tt>|<tt>false</tt>) to
- * publish a{@link ConditionalPermissionAdmin} service. The default is
+ * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not (
+ * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
+ * service. The default is
  * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_VALUE}.
  * </p>
  * <p>
- * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not 
- * (<tt>true</tt>|<tt>false</tt>) to
- * publish a{@link ConditionalPermissionAdmin} service. The default is
- * {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
+ * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not (
+ * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
+ * service. The default is {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
  * </p>
  * <p>
  * {@link SecurityConstants#KEYSTORE_FILE_PROP} - The keystore URL(s) to use as
  * trusted CA stores. The urls must be separated by a guard (i.e., <tt>|</tt>).
- * The default is
- * {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
+ * The default is {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
  * </p>
  * <p>
  * {@link SecurityConstants#KEYSTORE_PASS_PROP} - The keystore password(s) to
- * use for the given keystores. The passwords must be separated by a guard 
+ * use for the given keystores. The passwords must be separated by a guard
  * (i.e., <tt>|</tt>).The default is
  * {@link SecurityConstants#KEYSTORE_PASS_VALUE}.
  * </p>
  * <p>
  * {@link SecurityConstants#KEYSTORE_TYPE_PROP} - The keystore type(s) to use
- * for the given keystores. The types must be separated by a guard 
- * (i.e., <tt>|</tt>).The default is
- * {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
+ * for the given keystores. The types must be separated by a guard (i.e.,
+ * <tt>|</tt>).The default is {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
  * </p>
  * <p>
  * {@link SecurityConstants#CRL_FILE_PROP} - The CRL URL(s) to use for revoked
- * certificates. The urls must be separated by a guard (i.e., <tt>|</tt>).
- * The default is {@link SecurityConstants#CRL_FILE_VALUE}.
+ * certificates. The urls must be separated by a guard (i.e., <tt>|</tt>). The
+ * default is {@link SecurityConstants#CRL_FILE_VALUE}.
  * </p>
  * </p>
  */
 /*
  * TODO: using a string for passwords is bad. We need to investigate
- * alternatives. 
+ * alternatives.
  * 
- * TODO: we might want to allow for the recognized properties to
- * change without a restart. This is trick because we can not publish a managed
- * service due to not being able to import as we are an extension bundle.
+ * TODO: we might want to allow for the recognized properties to change without
+ * a restart. This is trick because we can not publish a managed service due to
+ * not being able to import as we are an extension bundle.
  */
 public final class SecurityActivator implements BundleActivator
 {
-    private SecurityProviderImpl m_provider = null;
-    private PropertiesCache m_dnsCache = null;
-    private PropertiesCache m_localCache = null;
-    private LocalPermissions m_localPermissions = null;
-
     public synchronized void start(BundleContext context) throws Exception
     {
         PermissionAdminImpl pai = null;
@@ -135,15 +123,14 @@
             SecurityConstants.ENABLE_PERMISSIONADMIN_PROP,
             SecurityConstants.ENABLE_PERMISSIONADMIN_VALUE)))
         {
-            File cache =
-                context.getDataFile("security" + File.separator + "pa.txt");
+            File cache = context.getDataFile("security" + File.separator
+                + "pa.txt");
             if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
             {
                 throw new IOException("Can't create cache file");
             }
-            pai =
-                new PermissionAdminImpl(permissions, new PropertiesCache(cache,
-                    tmp, action));
+            pai = new PermissionAdminImpl(permissions, new PropertiesCache(
+                cache, tmp, action));
         }
 
         ConditionalPermissionAdminImpl cpai = null;
@@ -152,92 +139,72 @@
             SecurityConstants.ENABLE_CONDPERMADMIN_PROP,
             SecurityConstants.ENABLE_CONDPERMADMIN_VALUE)))
         {
-            File cpaCache =
-                context.getDataFile("security" + File.separator + "cpa.txt");
-            if ((cpaCache == null) || (!cpaCache.isFile() && !cpaCache.createNewFile()))
+            File cpaCache = context.getDataFile("security" + File.separator
+                + "cpa.txt");
+            if ((cpaCache == null)
+                || (!cpaCache.isFile() && !cpaCache.createNewFile()))
             {
                 throw new IOException("Can't create cache file");
             }
-            File localCache = 
-                context.getDataFile("security" + File.separator + "local.txt");
-            if ((localCache == null) || (!localCache.isFile() && !localCache.createNewFile()))
-            {
-                throw new IOException("Can't create cache file");
-            }
-            
-            m_localCache = new PropertiesCache(localCache, tmp, action);
-            m_localPermissions  = new LocalPermissions(permissions, m_localCache);
-            
-            cpai =
-                new ConditionalPermissionAdminImpl(permissions, new Conditions(
-                    action), m_localPermissions,
-                    new PropertiesCache(cpaCache, tmp, action));
+
+            LocalPermissions localPermissions = new LocalPermissions(
+                permissions);
+
+            cpai = new ConditionalPermissionAdminImpl(permissions,
+                new Conditions(action), localPermissions, new PropertiesCache(
+                    cpaCache, tmp, action), pai);
         }
 
         if ((pai != null) || (cpai != null))
         {
-            String crlList =
-                getProperty(context, SecurityConstants.CRL_FILE_PROP,
-                    SecurityConstants.CRL_FILE_VALUE);
-            String storeList =
-                getProperty(context, SecurityConstants.KEYSTORE_FILE_PROP,
-                    SecurityConstants.KEYSTORE_FILE_VALUE);
-            String passwdList =
-                getProperty(context, SecurityConstants.KEYSTORE_PASS_PROP,
-                    SecurityConstants.KEYSTORE_PASS_VALUE);
-            String typeList =
-                getProperty(context, SecurityConstants.KEYSTORE_TYPE_PROP,
-                    SecurityConstants.KEYSTORE_TYPE_VALUE);
+            String crlList = getProperty(context,
+                SecurityConstants.CRL_FILE_PROP,
+                SecurityConstants.CRL_FILE_VALUE);
+            String storeList = getProperty(context,
+                SecurityConstants.KEYSTORE_FILE_PROP,
+                SecurityConstants.KEYSTORE_FILE_VALUE);
+            String passwdList = getProperty(context,
+                SecurityConstants.KEYSTORE_PASS_PROP,
+                SecurityConstants.KEYSTORE_PASS_VALUE);
+            String typeList = getProperty(context,
+                SecurityConstants.KEYSTORE_TYPE_PROP,
+                SecurityConstants.KEYSTORE_TYPE_VALUE);
+            String osgi_keystores = getProperty(context,
+                Constants.FRAMEWORK_TRUST_REPOSITORIES, null);
+            if (osgi_keystores != null)
+            {
+                StringTokenizer tok = new StringTokenizer(osgi_keystores,
+                    File.pathSeparator);
+
+                if (storeList.length() == 0)
+                {
+                    storeList += "file:" + tok.nextToken();
+                    passwdList += " ";
+                    typeList += "JKS";
+                }
+                while (tok.hasMoreTokens())
+                {
+                    storeList += "|file:" + tok.nextToken();
+                    passwdList += "| ";
+                    typeList += "|JKS";
+                }
+            }
 
             StringTokenizer storeTok = new StringTokenizer(storeList, "|");
             StringTokenizer passwdTok = new StringTokenizer(passwdList, "|");
             StringTokenizer typeTok = new StringTokenizer(typeList, "|");
 
-            if ((storeTok.countTokens() != passwdTok.countTokens())
-                || (passwdTok.countTokens() != typeTok.countTokens()))
+            if ((storeTok.countTokens() != typeTok.countTokens())
+                || (passwdTok.countTokens() != storeTok.countTokens()))
             {
                 throw new BundleException(
                     "Each CACerts keystore must have one type and one passwd entry and vice versa.");
             }
 
-            m_provider =
-                new SecurityProviderImpl(crlList, typeList, passwdList,
-                    storeList, pai, cpai, action);
+            SecurityProvider provider = new SecurityProviderImpl(crlList,
+                typeList, passwdList, storeList, pai, cpai, action);
 
-            File cache =
-                context.getDataFile("security" + File.separator + "dns.txt");
-            if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
-            {
-                throw new IOException("Can't create cache file");
-            }
-            m_dnsCache = new PropertiesCache(cache, tmp, action);
-
-            Map store = m_dnsCache.read(String[].class);
-
-            if (store != null)
-            {
-                BundleDNParser parser = m_provider.getParser();
-
-                for (Iterator iter = store.entrySet().iterator(); iter
-                    .hasNext();)
-                {
-                    Entry entry = (Entry) iter.next();
-                    String[] value = (String[]) entry.getValue();
-                    if ("none".equals(value[0]))
-                    {
-                        parser.put((String) entry.getKey(), null);
-                    }
-                    else if ("invalid".equals(value[0]))
-                    {
-                        parser.put((String) entry.getKey(), new String[0]);
-                    }
-                    else
-                    {
-                        parser.put((String) entry.getKey(), value);
-                    }
-                }
-            }
-            ((Felix) context.getBundle(0)).setSecurityProvider(m_provider);
+            ((Felix) context.getBundle(0)).setSecurityProvider(provider);
         }
 
         if (pai != null)
@@ -254,59 +221,7 @@
 
     public synchronized void stop(BundleContext context) throws Exception
     {
-        if (m_provider != null)
-        {
-            m_dnsCache.write(write(m_provider.getParser().getCache(), context));
-        }
-        if (m_localPermissions != null)
-        {
-           m_localCache.write(write(m_localPermissions.getStore(), context));
-        }
-        m_provider = null;
-        m_dnsCache = null;
-        m_localPermissions = null;
-    }
-
-    private Map write(Map cache, BundleContext context)
-    {
-        // Filter the cached dn chains and only store the latest for each 
-        // bundle. This is ok because the framework will prune old revisions
-        // after a restart. The format is <id>-<timestamp>
-        Map store = new HashMap();
-        Map index = new HashMap();
-        for (Iterator iter = cache.entrySet().iterator(); iter.hasNext();)
-        {
-            Entry entry = (Entry) iter.next();
-            
-            String key = (String) entry.getKey();
-            String id = key.substring(0, key.indexOf("-"));
-            String time = key.substring(key.indexOf("-") + 1);
-            Bundle bundle = context.getBundle(Long.parseLong(id));
-            long timeLong = Long.parseLong(time);
-            if ((bundle == null) || 
-                (bundle.getLastModified() > timeLong))
-            {
-                continue;
-            }
-            String last = (String) index.get(id);
-
-            if ((last == null)
-                || (Long.parseLong(last) < timeLong))
-            {
-                index.put(id, time);
-                Object[] dns = (Object[]) entry.getValue();
-                store.remove(id + "-" + last);
-                if ((dns != null) && (dns.length > 0))
-                {
-                    store.put(key, dns);
-                }
-                else
-                {
-                    store.put(key, (dns == null) ? new String[] {"none"} : new String[] {"invalid"});
-                }
-            }
-        }
-        return store;
+        ((Felix) context.getBundle(0)).setSecurityProvider(null);
     }
 
     private String getProperty(BundleContext context, String key,
@@ -314,7 +229,6 @@
     {
         String result = context.getProperty(key);
 
-        return ((result != null) && (result.trim().length() > 0)) ? result
-            : defaultValue;
+        return (result != null) ? result : defaultValue;
     }
 }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java b/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
index f7f4eb0..1fadadd 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
@@ -26,13 +26,13 @@
 import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
 import org.apache.felix.framework.security.util.TrustManager;
 import org.apache.felix.framework.security.verifier.BundleDNParser;
-import org.apache.felix.framework.security.verifier.SignerMatcher;
 import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.moduleloader.IModule;
 import org.osgi.framework.Bundle;
 
 /**
- * This class is the entry point to the security. It is used to determine whether
- * a given bundle is signed correctely and has permissions based on 
+ * This class is the entry point to the security. It is used to determine
+ * whether a given bundle is signed correctely and has permissions based on
  * PermissionAdmin or ConditionalPermissionAdmin.
  */
 public final class SecurityProviderImpl implements SecurityProvider
@@ -42,69 +42,49 @@
     private final ConditionalPermissionAdminImpl m_cpai;
     private final SecureAction m_action;
 
-    SecurityProviderImpl(String crlList, String typeList,
-        String passwdList, String storeList, PermissionAdminImpl pai,
+    SecurityProviderImpl(String crlList, String typeList, String passwdList,
+        String storeList, PermissionAdminImpl pai,
         ConditionalPermissionAdminImpl cpai, SecureAction action)
     {
         m_pai = pai;
         m_cpai = cpai;
         m_action = action;
-        m_parser =
-            new BundleDNParser(new TrustManager(crlList, typeList, passwdList,
-                storeList, m_action));
-    }
-
-    BundleDNParser getParser()
-    {
-        return m_parser;
+        m_parser = new BundleDNParser(new TrustManager(crlList, typeList,
+            passwdList, storeList, m_action));
     }
 
     /**
-     * If the given bundle is signed but can not be verified (e.g., missing files)
-     * then throw an exception.
+     * If the given bundle is signed but can not be verified (e.g., missing
+     * files) then throw an exception.
      */
     public void checkBundle(Bundle bundle) throws Exception
     {
-        m_parser.checkDNChains(
-            (Long.toString(bundle.getBundleId()) + "-" + bundle.getLastModified()), 
-            ((BundleImpl) bundle).getCurrentModule().getContent());
+        IModule module = ((BundleImpl) bundle).getCurrentModule();
+        m_parser.checkDNChains(module, module.getContent(),
+            Bundle.SIGNERS_TRUSTED);
     }
 
     /**
      * Get a signer matcher that can be used to match digital signed bundles.
      */
-    public Object getSignerMatcher(final Bundle bundle)
+    public Object getSignerMatcher(final Bundle bundle, int signersType)
     {
-        return new SignerMatcher(Long.toString(bundle.getBundleId()), 
-            bundle.getLastModified(),
-            ((BundleImpl) bundle).getCurrentModule().getContent(), 
-            m_parser);
+        IModule module = ((BundleImpl) bundle).getCurrentModule();
+        return m_parser.getDNChains(module, module.getContent(), signersType);
     }
 
-    ThreadLocal loopCheck = new ThreadLocal();
-    
     /**
-     * If we have a permissionadmin then ask that one first and have it
-     * decide in case there is a location bound. If not then either use its 
-     * default permission in case there is no conditional permission admin
-     * or else ask that one. 
+     * If we have a permissionadmin then ask that one first and have it decide
+     * in case there is a location bound. If not then either use its default
+     * permission in case there is no conditional permission admin or else ask
+     * that one.
      */
     public boolean hasBundlePermission(ProtectionDomain bundleProtectionDomain,
         Permission permission, boolean direct)
     {
-    	if (loopCheck.get() != null)
-    	{
-    		return true;
-    	}
-    	else
-    	{
-    	    loopCheck.set(this);
-    	}
-    	try
-    	{
-        BundleProtectionDomain pd =
-            (BundleProtectionDomain) bundleProtectionDomain;
+        BundleProtectionDomain pd = (BundleProtectionDomain) bundleProtectionDomain;
         BundleImpl bundle = pd.getBundle();
+        IModule module = pd.getModule();
 
         if (bundle.getBundleId() == 0)
         {
@@ -116,13 +96,22 @@
         Boolean result = null;
         if (m_pai != null)
         {
-            result =
-                m_pai.hasPermission(bundle.getLocation(), pd.getBundle(),
-                    permission, m_cpai, pd);
+            result = m_pai.hasPermission(bundle._getLocation(), pd.getBundle(),
+                permission, m_cpai, pd, bundle.getCurrentModule().getContent());
         }
 
         if (result != null)
         {
+            if ((m_cpai != null) && !direct)
+            {
+                boolean allow = result.booleanValue();
+                if (!allow)
+                {
+                    m_cpai.clearPD();
+                    return false;
+                }
+                return m_cpai.handlePAHandle(pd);
+            }
             return result.booleanValue();
         }
 
@@ -130,10 +119,7 @@
         {
             try
             {
-                return m_cpai.hasPermission(bundle, 
-                    bundle.getCurrentModule().getContent(), 
-                    bundle.getBundleId() + "-" + 
-                    bundle.getLastModified(),null, pd,
+                return m_cpai.hasPermission(module, module.getContent(), pd,
                     permission, direct, m_pai);
             }
             catch (Exception e)
@@ -144,8 +130,5 @@
         }
 
         return false;
-    	} finally {
-    		loopCheck.set(null);
-    	}
     }
 }
\ No newline at end of file
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java b/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
index 9ac88d9..790e185 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
@@ -18,38 +18,29 @@
  */
 package org.apache.felix.framework.security;
 
-import java.io.File;
-
 public interface SecurityConstants
 {
     public static final String KEYSTORE_FILE_PROP = "felix.keystore";
 
-    public static final String KEYSTORE_FILE_VALUE = "file:" +
-        System.getProperty("java.home") + File.separatorChar + "lib"
-            + File.separatorChar + "security" + File.separatorChar + "cacerts"
-            + "|file:" + System.getProperty("user.home") + File.separatorChar
-            + ".keystore";
+    public static final String KEYSTORE_FILE_VALUE = "";
 
     public static final String KEYSTORE_TYPE_PROP = "felix.keystore.type";
 
-    public static final String KEYSTORE_TYPE_VALUE = "JKS" + "|" + "JKS";
+    public static final String KEYSTORE_TYPE_VALUE = "";
 
     public static final String KEYSTORE_PASS_PROP = "felix.keystore.pass";
 
-    public static final String KEYSTORE_PASS_VALUE =
-        "changeit" + "|" + "changeit";
+    public static final String KEYSTORE_PASS_VALUE = "";
 
     public static final String CRL_FILE_PROP = "felix.crl";
 
     public static final String CRL_FILE_VALUE = "";
 
-    public static final String ENABLE_CONDPERMADMIN_PROP =
-        "felix.security.conpermadmin";
+    public static final String ENABLE_CONDPERMADMIN_PROP = "felix.security.conpermadmin";
 
     public static final String ENABLE_CONDPERMADMIN_VALUE = "true";
 
-    public static final String ENABLE_PERMISSIONADMIN_PROP =
-        "felix.security.permissionadmin";
+    public static final String ENABLE_PERMISSIONADMIN_PROP = "felix.security.permissionadmin";
 
     public static final String ENABLE_PERMISSIONADMIN_VALUE = "true";
 }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
index ad73e75..04e6de7 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
@@ -19,70 +19,222 @@
 package org.apache.felix.framework.security.condpermadmin;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URL;
 import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.DomainCombiner;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.Permission;
+import java.security.Principal;
 import java.security.ProtectionDomain;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.X509Certificate;
+import java.util.AbstractSet;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
 import java.util.Map.Entry;
 
+import org.apache.felix.framework.BundleProtectionDomain;
+import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
 import org.apache.felix.framework.security.util.Conditions;
 import org.apache.felix.framework.security.util.LocalPermissions;
 import org.apache.felix.framework.security.util.Permissions;
 import org.apache.felix.framework.security.util.PropertiesCache;
 import org.apache.felix.framework.util.IteratorToEnumeration;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.moduleloader.ICapability;
 import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IModule;
+import org.apache.felix.moduleloader.IRequirement;
+import org.apache.felix.moduleloader.IWire;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 import org.osgi.service.condpermadmin.ConditionInfo;
 import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
 import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
+import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
 import org.osgi.service.permissionadmin.PermissionInfo;
 
 /**
  * An implementation of the ConditionalPermissionAdmin service that doesn't need
  * to have a framework specific security manager set. It use the DomainGripper
- * to know what bundleprotectiondomains are expected.  
+ * to know what bundleprotectiondomains are expected.
  */
 public final class ConditionalPermissionAdminImpl implements
     ConditionalPermissionAdmin
 {
+    private static class OrderedHashMap extends HashMap
+    {
+        private final List m_order = new ArrayList();
+
+        public Object put(Object key, Object value)
+        {
+            Object result = super.put(key, value);
+            if (result != value)
+            {
+                m_order.remove(key);
+                m_order.add(key);
+            }
+            return result;
+        };
+
+        public void putAll(Map map)
+        {
+            for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
+            {
+                Entry entry = (Entry) iter.next();
+                put(entry.getKey(), entry.getValue());
+            }
+        };
+
+        public Set keySet()
+        {
+            return new AbstractSet()
+            {
+                public Iterator iterator()
+                {
+                    return m_order.iterator();
+                }
+
+                public int size()
+                {
+                    return m_order.size();
+                }
+
+            };
+        };
+
+        public Set entrySet()
+        {
+            return new AbstractSet()
+            {
+
+                public Iterator iterator()
+                {
+                    return new Iterator()
+                    {
+                        Iterator m_iter = m_order.iterator();
+
+                        public boolean hasNext()
+                        {
+                            return m_iter.hasNext();
+                        }
+
+                        public Object next()
+                        {
+                            final Object key = m_iter.next();
+                            return new Entry()
+                            {
+
+                                public Object getKey()
+                                {
+                                    return key;
+                                }
+
+                                public Object getValue()
+                                {
+                                    return get(key);
+                                }
+
+                                public Object setValue(Object arg0)
+                                {
+                                    throw new IllegalStateException(
+                                        "Not Implemented");
+                                }
+                            };
+                        }
+
+                        public void remove()
+                        {
+                            throw new IllegalStateException("Not Implemented");
+                        }
+
+                    };
+                }
+
+                public int size()
+                {
+                    return m_order.size();
+                }
+
+            };
+        };
+
+        public Collection values()
+        {
+            List result = new ArrayList();
+            for (Iterator iter = m_order.iterator(); iter.hasNext();)
+            {
+                result.add(super.get(iter.next()));
+            }
+            return result;
+        };
+
+        public Object remove(Object key)
+        {
+            Object result = super.remove(key);
+            if (result != null)
+            {
+                m_order.remove(key);
+            }
+            return result;
+        };
+
+        public void clear()
+        {
+            super.clear();
+            m_order.clear();
+        };
+    };
+
     private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
     private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
-    private final Map m_condPermInfos = new HashMap();
+    private final Map m_condPermInfos = new OrderedHashMap();
     private final PropertiesCache m_propertiesCache;
     private final Permissions m_permissions;
     private final Conditions m_conditions;
     private final LocalPermissions m_localPermissions;
+    private final PermissionAdminImpl m_pai;
 
     public ConditionalPermissionAdminImpl(Permissions permissions,
         Conditions condtions, LocalPermissions localPermissions,
-        PropertiesCache cache) throws IOException
+        PropertiesCache cache, PermissionAdminImpl pai) throws IOException
     {
         m_propertiesCache = cache;
         m_permissions = permissions;
         m_conditions = condtions;
         m_localPermissions = localPermissions;
+        Map old = new OrderedHashMap();
         // Now try to restore the cache.
-        Map old = m_propertiesCache.read(ConditionalPermissionInfoImpl.class);
-        if (old != null)
+        m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
+        for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
         {
-            for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
-            {
-                Entry entry = (Entry) iter.next();
-                String name = (String) entry.getKey();
-                ConditionalPermissionInfoImpl cpi =
-                    ((ConditionalPermissionInfoImpl) entry.getValue());
-                m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(
-                    name, cpi._getConditionInfos(), cpi._getPermissionInfos(),
-                    this));
-            }
+            Entry entry = (Entry) iter.next();
+            String name = (String) entry.getKey();
+            ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
+                .getValue());
+            m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
+                cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
+                    .isAllow()));
         }
+        m_pai = pai;
     }
 
     public ConditionalPermissionInfo addConditionalPermissionInfo(
@@ -93,9 +245,8 @@
         {
             ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
         }
-        ConditionalPermissionInfoImpl result =
-            new ConditionalPermissionInfoImpl(notNull(conditions),
-                notNull(permissions), this);
+        ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
+            notNull(conditions), notNull(permissions), this, true);
 
         return write(result.getName(), result);
     }
@@ -109,7 +260,8 @@
 
             synchronized (m_condPermInfos)
             {
-                tmp = new HashMap(m_condPermInfos);
+                tmp = new OrderedHashMap();
+                tmp.putAll(m_condPermInfos);
 
                 if ((name != null) && (cpi != null))
                 {
@@ -133,8 +285,11 @@
             {
                 synchronized (m_condPermInfos)
                 {
-                    m_condPermInfos.clear();
-                    m_condPermInfos.putAll(tmp);
+                    if (tmp != null)
+                    {
+                        m_condPermInfos.clear();
+                        m_condPermInfos.putAll(tmp);
+                    }
                 }
                 ex.printStackTrace();
                 throw new IllegalStateException(ex.getMessage());
@@ -146,28 +301,485 @@
         }
     }
 
-    // TODO: this is pretty much untested so it might not work like this
-    public AccessControlContext getAccessControlContext(String[] signers)
+    private static class FakeBundle implements Bundle
     {
-        final String[] finalSigners =
-            (String[]) notNull(signers).toArray(new String[0]);
-        return new AccessControlContext(AccessController.getContext(),
-            new DomainCombiner()
+        private final Map m_certs;
+
+        public FakeBundle(Map certs)
+        {
+            m_certs = Collections.unmodifiableMap(certs);
+        }
+
+        public Enumeration findEntries(String arg0, String arg1, boolean arg2)
+        {
+            return null;
+        }
+
+        public BundleContext getBundleContext()
+        {
+            return null;
+        }
+
+        public long getBundleId()
+        {
+            return -1;
+        }
+
+        public URL getEntry(String arg0)
+        {
+            return null;
+        }
+
+        public Enumeration getEntryPaths(String arg0)
+        {
+            return null;
+        }
+
+        public Dictionary getHeaders()
+        {
+            return new Hashtable();
+        }
+
+        public Dictionary getHeaders(String arg0)
+        {
+            return new Hashtable();
+        }
+
+        public long getLastModified()
+        {
+            return 0;
+        }
+
+        public String getLocation()
+        {
+            return "";
+        }
+
+        public ServiceReference[] getRegisteredServices()
+        {
+            return null;
+        }
+
+        public URL getResource(String arg0)
+        {
+            return null;
+        }
+
+        public Enumeration getResources(String arg0) throws IOException
+        {
+            return null;
+        }
+
+        public ServiceReference[] getServicesInUse()
+        {
+            return null;
+        }
+
+        public Map getSignerCertificates(int arg0)
+        {
+            return m_certs;
+        }
+
+        public int getState()
+        {
+            return Bundle.UNINSTALLED;
+        }
+
+        public String getSymbolicName()
+        {
+            return null;
+        }
+
+        public Version getVersion()
+        {
+            return Version.emptyVersion;
+        }
+
+        public boolean hasPermission(Object arg0)
+        {
+            return false;
+        }
+
+        public Class loadClass(String arg0) throws ClassNotFoundException
+        {
+            return null;
+        }
+
+        public void start() throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void start(int arg0) throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void stop() throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void stop(int arg0) throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void uninstall() throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void update() throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public void update(InputStream arg0) throws BundleException
+        {
+            throw new IllegalStateException();
+        }
+
+        public boolean equals(Object o)
+        {
+            return this == o;
+        }
+
+        public int hashCode()
+        {
+            return System.identityHashCode(this);
+        }
+    }
+
+    private static class FakeCert extends X509Certificate
+    {
+        private final Principal m_principal;
+
+        public FakeCert(final String principal)
+        {
+            m_principal = new Principal()
             {
-                public ProtectionDomain[] combine(ProtectionDomain[] arg0,
-                    ProtectionDomain[] arg1)
+                public String getName()
                 {
-                    return new ProtectionDomain[] { new ProtectionDomain(null,
-                        null)
-                    {
-                        public boolean implies(Permission permission)
-                        {
-                            return hasPermission(null, null, null, finalSigners,
-                                this, permission, true, null);
-                        }
-                    } };
+                    return principal;
                 }
-            });
+            };
+        }
+
+        public void checkValidity()
+            throws java.security.cert.CertificateExpiredException,
+            java.security.cert.CertificateNotYetValidException
+        {
+
+        }
+
+        public void checkValidity(Date date)
+            throws java.security.cert.CertificateExpiredException,
+            java.security.cert.CertificateNotYetValidException
+        {
+        }
+
+        public int getBasicConstraints()
+        {
+            return 0;
+        }
+
+        public Principal getIssuerDN()
+        {
+            return null;
+        }
+
+        public boolean[] getIssuerUniqueID()
+        {
+            return null;
+        }
+
+        public boolean[] getKeyUsage()
+        {
+            return null;
+        }
+
+        public Date getNotAfter()
+        {
+            return null;
+        }
+
+        public Date getNotBefore()
+        {
+            return null;
+        }
+
+        public BigInteger getSerialNumber()
+        {
+            return null;
+        }
+
+        public String getSigAlgName()
+        {
+            return null;
+        }
+
+        public String getSigAlgOID()
+        {
+            return null;
+        }
+
+        public byte[] getSigAlgParams()
+        {
+            return null;
+        }
+
+        public byte[] getSignature()
+        {
+            return null;
+        }
+
+        public Principal getSubjectDN()
+        {
+            return m_principal;
+        }
+
+        public boolean[] getSubjectUniqueID()
+        {
+            return null;
+        }
+
+        public byte[] getTBSCertificate()
+            throws java.security.cert.CertificateEncodingException
+        {
+            return null;
+        }
+
+        public int getVersion()
+        {
+            return 0;
+        }
+
+        public byte[] getEncoded()
+            throws java.security.cert.CertificateEncodingException
+        {
+            return null;
+        }
+
+        public PublicKey getPublicKey()
+        {
+            return null;
+        }
+
+        public String toString()
+        {
+            return m_principal.getName();
+        }
+
+        public void verify(PublicKey key)
+            throws java.security.cert.CertificateException,
+            NoSuchAlgorithmException, InvalidKeyException,
+            NoSuchProviderException, SignatureException
+        {
+
+        }
+
+        public void verify(PublicKey key, String sigProvider)
+            throws java.security.cert.CertificateException,
+            NoSuchAlgorithmException, InvalidKeyException,
+            NoSuchProviderException, SignatureException
+        {
+
+        }
+
+        public Set getCriticalExtensionOIDs()
+        {
+            return null;
+        }
+
+        public byte[] getExtensionValue(String arg0)
+        {
+            return null;
+        }
+
+        public Set getNonCriticalExtensionOIDs()
+        {
+            return null;
+        }
+
+        public boolean hasUnsupportedCriticalExtension()
+        {
+            return false;
+        }
+
+        public boolean equals(Object o)
+        {
+            return this == o;
+        }
+
+        public int hashCode()
+        {
+            return System.identityHashCode(this);
+        }
+
+    }
+
+    public AccessControlContext getAccessControlContext(final String[] signers)
+    {
+        Map certificates = new HashMap();
+        for (int i = 0; i < signers.length; i++)
+        {
+            StringTokenizer tok = new StringTokenizer(signers[i], ";");
+            List certsList = new ArrayList();
+            while (tok.hasMoreTokens())
+            {
+                certsList.add(tok.nextToken());
+            }
+            String[] certs = (String[]) certsList.toArray(new String[certsList
+                .size()]);
+
+            X509Certificate key = new FakeCert(certs[0]);
+            List certList = new ArrayList();
+            certificates.put(key, certList);
+            certList.add(key);
+            for (int j = 1; j < certs.length; j++)
+            {
+                certList.add(new FakeCert(certs[j]));
+            }
+        }
+        final Bundle fake = new FakeBundle(certificates);
+        ProtectionDomain domain = new ProtectionDomain(null, null)
+        {
+            public boolean implies(Permission permission)
+            {
+                List posts = new ArrayList();
+                Boolean result = m_pai.hasPermission("", fake, permission,
+                    ConditionalPermissionAdminImpl.this, this, null);
+                if (result != null)
+                {
+                    return result.booleanValue();
+                }
+                if (eval(posts, new IModule()
+                {
+
+                    public Bundle getBundle()
+                    {
+                        return fake;
+                    }
+
+                    public ICapability[] getCapabilities()
+                    {
+                        return null;
+                    }
+
+                    public Class getClassByDelegation(String arg0)
+                        throws ClassNotFoundException
+                    {
+                        return null;
+                    }
+
+                    public IContent getContent()
+                    {
+                        return null;
+                    }
+
+                    public int getDeclaredActivationPolicy()
+                    {
+                        return 0;
+                    }
+
+                    public IRequirement[] getDynamicRequirements()
+                    {
+                        return null;
+                    }
+
+                    public URL getEntry(String arg0)
+                    {
+                        return null;
+                    }
+
+                    public Map getHeaders()
+                    {
+                        return null;
+                    }
+
+                    public String getId()
+                    {
+                        return null;
+                    }
+
+                    public InputStream getInputStream(int arg0, String arg1)
+                        throws IOException
+                    {
+                        return null;
+                    }
+
+                    public R4Library[] getNativeLibraries()
+                    {
+                        return null;
+                    }
+
+                    public IRequirement[] getRequirements()
+                    {
+                        return null;
+                    }
+
+                    public URL getResourceByDelegation(String arg0)
+                    {
+                        return null;
+                    }
+
+                    public Enumeration getResourcesByDelegation(String arg0)
+                    {
+                        return null;
+                    }
+
+                    public Object getSecurityContext()
+                    {
+                        return null;
+                    }
+
+                    public String getSymbolicName()
+                    {
+                        return null;
+                    }
+
+                    public Version getVersion()
+                    {
+                        return null;
+                    }
+
+                    public IWire[] getWires()
+                    {
+                        return null;
+                    }
+
+                    public boolean hasInputStream(int arg0, String arg1)
+                        throws IOException
+                    {
+                        return false;
+                    }
+
+                    public boolean isExtension()
+                    {
+                        return false;
+                    }
+
+                    public boolean isResolved()
+                    {
+                        return false;
+                    }
+
+                    public void setSecurityContext(Object arg0)
+                    {
+                    }
+                }, permission, m_pai))
+                {
+                    if (!posts.isEmpty())
+                    {
+                        return m_conditions.evalRecursive(posts);
+                    }
+                    return true;
+                }
+                return false;
+            }
+        };
+        return new AccessControlContext(new ProtectionDomain[] { domain });
     }
 
     public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
@@ -185,7 +797,7 @@
 
         if (result == null)
         {
-            result = new ConditionalPermissionInfoImpl(this, name);
+            result = new ConditionalPermissionInfoImpl(this, name, true);
 
             result = write(result.getName(), result);
         }
@@ -219,14 +831,13 @@
         {
             synchronized (m_condPermInfos)
             {
-                result =
-                    (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
+                result = (ConditionalPermissionInfoImpl) m_condPermInfos
+                    .get(name);
 
                 if (result == null)
                 {
-                    result =
-                        new ConditionalPermissionInfoImpl(name, conditions,
-                            permissions, this);
+                    result = new ConditionalPermissionInfoImpl(name,
+                        conditions, permissions, this, true);
                 }
                 else
                 {
@@ -236,8 +847,8 @@
         }
         else
         {
-            result =
-                new ConditionalPermissionInfoImpl(conditions, permissions, this);
+            result = new ConditionalPermissionInfoImpl(conditions, permissions,
+                this, true);
         }
 
         return write(result.getName(), result);
@@ -284,87 +895,84 @@
 
     /**
      * This method does the actual permission check. If it is not a direct check
-     * it will try to determine the other bundle domains that will follow 
-     * automatically in case this is the first check in one permission check.
-     * If not then it will keep track of which domains we have already see.
-     * While it keeps track it builds up a list of postponed tuples which
-     * it will evaluate at the last domain. See the core spec 9.5.1 and following
-     * for a general description.
+     * it will try to determine the other bundle domains that will follow
+     * automatically in case this is the first check in one permission check. If
+     * not then it will keep track of which domains we have already see. While
+     * it keeps track it builds up a list of postponed tuples which it will
+     * evaluate at the last domain. See the core spec 9.5.1 and following for a
+     * general description.
      * 
-     * @param felixBundle the bundle in question.
-     * @param loader the content loader of the bundle to get access to the jar 
-     *    to check for local permissions.
-     * @param root the bundle id.
-     * @param signers the signers (this is to support the ACC based on signers) 
-     * @param pd the bundle protection domain
-     * @param permission the permission currently checked
-     * @param direct whether this is a direct check or not. direct check will not
-     *     expect any further bundle domains on the stack
-     * @return true in case the permission is granted or there are postponed tuples
-     *     false if not. Again, see the spec for more explanations.
+     * @param felixBundle
+     *            the bundle in question.
+     * @param loader
+     *            the content loader of the bundle to get access to the jar to
+     *            check for local permissions.
+     * @param root
+     *            the bundle id.
+     * @param signers
+     *            the signers (this is to support the ACC based on signers)
+     * @param pd
+     *            the bundle protection domain
+     * @param permission
+     *            the permission currently checked
+     * @param direct
+     *            whether this is a direct check or not. direct check will not
+     *            expect any further bundle domains on the stack
+     * @return true in case the permission is granted or there are postponed
+     *         tuples false if not. Again, see the spec for more explanations.
      */
-    public boolean hasPermission(Bundle felixBundle, IContent content, String root, 
-        String[] signers, ProtectionDomain pd, Permission permission,
-        boolean direct, Object admin)
+    public boolean hasPermission(IModule module, IContent content,
+        ProtectionDomain pd, Permission permission, boolean direct, Object admin)
     {
         // System.out.println(felixBundle + "-" + permission);
         List domains = null;
         List tuples = null;
         Object[] entry = null;
-        // first see whether this is the normal case (the special case is for 
+        // first see whether this is the normal case (the special case is for
         // the ACC based on signers).
-        if (signers == null)
+        // In case of a direct call we don't need to look for other pds
+        if (direct)
         {
-            // In case of  a direct call we don't need to look for other pds
-            if (direct)
+            domains = new ArrayList();
+            tuples = new ArrayList();
+            domains.add(pd);
+        }
+        else
+        {
+            // Get the other pds from the stck
+            entry = (Object[]) m_stack.get();
+
+            // if there are none then get them from the gripper
+            if (entry == null)
             {
-                domains = new ArrayList();
-                tuples = new ArrayList();
-                domains.add(pd);
+                entry = new Object[] { new ArrayList(DomainGripper.grab()),
+                    new ArrayList() };
             }
             else
             {
-                // Get the other pds from the stck
-                entry = (Object[]) m_stack.get();
+                m_stack.set(null);
+            }
 
-                // if there are none then get them from the gripper
-                if (entry == null)
-                {
-                    entry =
-                        new Object[] { new ArrayList(DomainGripper.grab()),
-                            new ArrayList() };
-                }
-                else
-                {
-                    m_stack.set(null);
-                }
-
-                domains = (List) entry[0];
-                tuples = (List) entry[1];
-                if (!domains.contains(pd))
-                {
-                    // We have been called directly without the direct flag
-                    domains.clear();
-                    domains.add(pd);
-                }
+            domains = (List) entry[0];
+            tuples = (List) entry[1];
+            if (!domains.contains(pd))
+            {
+                // We have been called directly without the direct flag
+                domains.clear();
+                domains.add(pd);
             }
         }
 
         // check the local permissions. they need to all the permission if there
         // are any
-        if (!m_localPermissions.implies(root, content, felixBundle, permission))
+        if (!impliesLocal(module.getBundle(), content, permission))
         {
             return false;
         }
 
         List posts = new ArrayList();
 
-        boolean result = eval(posts, felixBundle, signers, permission, admin);
-
-        if (signers != null)
-        {
-            return result;
-        }
+        boolean result = eval(posts, module, permission, admin);
 
         domains.remove(pd);
 
@@ -378,7 +986,8 @@
         if (domains.isEmpty())
         {
             m_stack.set(null);
-            // Now eval the postponed tupels. if the previous eval did return false
+            // Now eval the postponed tupels. if the previous eval did return
+            // false
             // tuples will be empty so we don't return from here.
             if (!tuples.isEmpty())
             {
@@ -387,7 +996,8 @@
         }
         else
         {
-            // this is to support recursive permission checks. In case we trigger
+            // this is to support recursive permission checks. In case we
+            // trigger
             // a permission check while eval the stack is null until this point
             m_stack.set(entry);
         }
@@ -395,6 +1005,12 @@
         return result;
     }
 
+    public boolean impliesLocal(Bundle felixBundle, IContent content,
+        Permission permission)
+    {
+        return m_localPermissions.implies(content, felixBundle, permission);
+    }
+
     public boolean isEmpty()
     {
         synchronized (m_condPermInfos)
@@ -408,8 +1024,8 @@
     // then we make sure their permissions imply the permission and add them
     // to the list of posts. Return true in case we pass or have posts
     // else falls and clear the posts first.
-    private boolean eval(List posts, Bundle bundle, String[] signers,
-        Permission permission, Object admin)
+    private boolean eval(List posts, IModule module, Permission permission,
+        Object admin)
     {
         List condPermInfos = null;
 
@@ -423,25 +1039,26 @@
         }
 
         // Check for implicit permissions like access to file area
-        if ((bundle != null)
-            && m_permissions.getPermissions(m_permissions.getImplicit(bundle))
-                .implies(permission, bundle))
+        if (m_permissions.getPermissions(
+            m_permissions.getImplicit(module.getBundle())).implies(permission,
+            module.getBundle()))
         {
             return true;
         }
-
+        List pls = new ArrayList();
         // now do the real thing
         for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
         {
-            ConditionalPermissionInfoImpl cpi =
-                (ConditionalPermissionInfoImpl) iter.next();
+            ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
+                .next();
 
             ConditionInfo[] conditions = cpi._getConditionInfos();
 
             List currentPosts = new ArrayList();
 
-            if (!m_conditions.getConditions(bundle, signers, conditions)
-                .isSatisfied(currentPosts))
+            Conditions conds = m_conditions.getConditions(module, conditions);
+            if (!conds.isSatisfied(currentPosts, m_permissions
+                .getPermissions(cpi._getPermissionInfos()), permission))
             {
                 continue;
             }
@@ -454,13 +1071,127 @@
 
             if (currentPosts.isEmpty())
             {
-                posts.clear();
+                pls.add(new Object[] { cpi, null });
+                break;
+            }
+            pls.add(new Object[] { cpi, currentPosts, conds });
+        }
+        while (pls.size() > 1)
+        {
+            if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
+                .size() - 1))[0]).isAllow())
+            {
+                pls.remove(pls.size() - 1);
+            }
+            else
+            {
+                break;
+            }
+        }
+        if (pls.size() == 1)
+        {
+            if (((Object[]) pls.get(0))[1] != null)
+            {
+                posts.add(pls.get(0));
+            }
+            return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
+                .isAllow();
+        }
+        for (Iterator iter = pls.iterator(); iter.hasNext();)
+        {
+            posts.add(iter.next());
+        }
+        return !posts.isEmpty();
+    }
+
+    public ConditionalPermissionInfo newConditionalPermissionInfo(
+        String encodedConditionalPermissionInfo)
+    {
+        return new ConditionalPermissionInfoImpl(
+            encodedConditionalPermissionInfo);
+    }
+
+    public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
+        ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
+    {
+        return new ConditionalPermissionInfoImpl(name, conditions, permissions,
+            ConditionalPermissionAdminImpl.this, access
+                .equals(ConditionalPermissionInfo.ALLOW));
+    }
+
+    public ConditionalPermissionUpdate newConditionalPermissionUpdate()
+    {
+        return new ConditionalPermissionUpdate()
+        {
+            List current = null;
+            List out = null;
+            {
+                synchronized (m_condPermInfos)
+                {
+                    current = new ArrayList(m_condPermInfos.values());
+                    out = new ArrayList(m_condPermInfos.values());
+                }
+            }
+
+            public boolean commit()
+            {
+                synchronized (m_condPermInfos)
+                {
+                    if (current.equals(new ArrayList(m_condPermInfos.values())))
+                    {
+                        m_condPermInfos.clear();
+                        write(null, null);
+                        for (Iterator iter = out.iterator(); iter.hasNext();)
+                        {
+                            ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
+                                .next();
+                            write(cpii.getName(), cpii);
+                        }
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
                 return true;
             }
 
-            posts.add(currentPosts);
+            public List getConditionalPermissionInfos()
+            {
+                return out;
+            }
+        };
+    }
+
+    public boolean handlePAHandle(BundleProtectionDomain pd)
+    {
+        Object[] entry = (Object[]) m_stack.get();
+
+        if (entry == null)
+        {
+            entry = new Object[] { new ArrayList(DomainGripper.grab()),
+                new ArrayList() };
         }
 
-        return !posts.isEmpty();
+        ((List) entry[0]).remove(pd);
+        if (((List) entry[0]).isEmpty())
+        {
+            m_stack.set(null);
+            if (!((List) entry[1]).isEmpty())
+            {
+                return m_conditions.evalRecursive(((List) entry[1]));
+            }
+        }
+        else
+        {
+            m_stack.set(entry);
+        }
+
+        return true;
+    }
+
+    public void clearPD()
+    {
+        m_stack.set(null);
     }
 }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
index cfc4cb8..4e4bc13 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
@@ -30,15 +30,17 @@
 
 /**
  * Simple storage class for condperminfos. Additionally, this class can be used
- * to encode and decode infos. 
+ * to encode and decode infos.
  */
-public final class ConditionalPermissionInfoImpl implements ConditionalPermissionInfo
+public final class ConditionalPermissionInfoImpl implements
+    ConditionalPermissionInfo
 {
     private static final Random RANDOM = new Random();
     static final ConditionInfo[] CONDITION_INFO = new ConditionInfo[0];
     static final PermissionInfo[] PERMISSION_INFO = new PermissionInfo[0];
     private final Object m_lock = new Object();
     private final String m_name;
+    private final boolean m_allow;
     private volatile ConditionalPermissionAdminImpl m_cpai;
     private ConditionInfo[] m_conditions;
     private PermissionInfo[] m_permissions;
@@ -46,16 +48,18 @@
     public ConditionalPermissionInfoImpl(String encoded)
     {
         StringTokenizer tok = new StringTokenizer(encoded, "\n");
-        if (!tok.nextToken().trim().equals("{"))
+        String access = tok.nextToken().trim();
+        if (!(access.equals("ALLOW {") || access.equals("DENY {")))
         {
             throw new IllegalArgumentException();
         }
+        m_allow = access.equals("ALLOW {");
         m_cpai = null;
         m_name = tok.nextToken().trim().substring(1);
         List conditions = new ArrayList();
         List permissions = new ArrayList();
-        for (String current = tok.nextToken().trim();; current =
-            tok.nextToken().trim())
+        for (String current = tok.nextToken().trim();; current = tok
+            .nextToken().trim())
         {
             if (current.equals("}"))
             {
@@ -78,19 +82,18 @@
             }
         }
 
-        m_conditions =
-            conditions.isEmpty() ? CONDITION_INFO
-                : (ConditionInfo[]) conditions
-                    .toArray(new ConditionInfo[conditions.size()]);
-        m_permissions =
-            permissions.isEmpty() ? PERMISSION_INFO
-                : (PermissionInfo[]) permissions
-                    .toArray(new PermissionInfo[permissions.size()]);
+        m_conditions = conditions.isEmpty() ? CONDITION_INFO
+            : (ConditionInfo[]) conditions.toArray(new ConditionInfo[conditions
+                .size()]);
+        m_permissions = permissions.isEmpty() ? PERMISSION_INFO
+            : (PermissionInfo[]) permissions
+                .toArray(new PermissionInfo[permissions.size()]);
     }
 
     public ConditionalPermissionInfoImpl(ConditionalPermissionAdminImpl cpai,
-        String name)
+        String name, boolean access)
     {
+        m_allow = access;
         m_name = name;
         m_cpai = cpai;
         m_conditions = CONDITION_INFO;
@@ -98,8 +101,10 @@
     }
 
     public ConditionalPermissionInfoImpl(ConditionInfo[] conditions,
-        PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai)
+        PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai,
+        boolean access)
     {
+        m_allow = access;
         m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
         m_cpai = cpai;
         m_conditions = conditions;
@@ -108,9 +113,11 @@
 
     public ConditionalPermissionInfoImpl(String name,
         ConditionInfo[] conditions, PermissionInfo[] permisions,
-        ConditionalPermissionAdminImpl cpai)
+        ConditionalPermissionAdminImpl cpai, boolean access)
     {
-        m_name = name;
+        m_allow = access;
+        m_name = (name != null) ? name : Long.toString(RANDOM.nextLong()
+            ^ System.currentTimeMillis());
         m_conditions = conditions;
         m_permissions = permisions;
         m_cpai = cpai;
@@ -182,6 +189,7 @@
     public String getEncoded()
     {
         StringBuffer buffer = new StringBuffer();
+        buffer.append(m_allow ? "ALLOW " : "DENY ");
         buffer.append('{');
         buffer.append('\n');
         buffer.append('#');
@@ -209,4 +217,15 @@
     {
         return getEncoded();
     }
+
+    public String getAccessDecision()
+    {
+        return m_allow ? ConditionalPermissionInfo.ALLOW
+            : ConditionalPermissionInfo.DENY;
+    }
+
+    public boolean isAllow()
+    {
+        return m_allow;
+    }
 }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
index ed0dd0c..c9c299f 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
@@ -31,19 +31,19 @@
 import org.apache.felix.framework.BundleProtectionDomain;
 
 /**
- * This class is a hack to get all BundleProtectionDomains currently on the 
+ * This class is a hack to get all BundleProtectionDomains currently on the
  * security stack. This way we don't need to have our own security manager set.
  */
 final class DomainGripper implements DomainCombiner, PrivilegedAction
 {
-    private static final ProtectionDomain[] ALL_PERMISSION_PD =
-        new ProtectionDomain[] { new ProtectionDomain(null, null)
+    private static final ProtectionDomain[] ALL_PERMISSION_PD = new ProtectionDomain[] { new ProtectionDomain(
+        null, null)
+    {
+        public boolean implies(Permission perm)
         {
-            public boolean implies(Permission perm)
-            {
-                return true;
-            }
-        } };
+            return true;
+        }
+    } };
 
     // A per thread cache of DomainGripper objects. We might want to wrap them
     // in a softreference eventually
@@ -56,8 +56,8 @@
     private AccessControlContext m_system = null;
 
     /**
-     * Get all bundle protection domains and add them to the m_domains. Then 
-     * return the ALL_PERMISSION_PD. 
+     * Get all bundle protection domains and add them to the m_domains. Then
+     * return the ALL_PERMISSION_PD.
      */
     public ProtectionDomain[] combine(ProtectionDomain[] current,
         ProtectionDomain[] assigned)
@@ -84,7 +84,7 @@
     }
 
     /**
-     * Get the current bundle protection domains on the stack up to the last 
+     * Get the current bundle protection domains on the stack up to the last
      * privileged call.
      */
     public static List grab()
@@ -107,8 +107,8 @@
         gripper.m_system = AccessController.getContext();
 
         // and merge it with the current combiner (i.e., gripper)
-        AccessControlContext context =
-            (AccessControlContext) AccessController.doPrivileged(gripper);
+        AccessControlContext context = (AccessControlContext) AccessController
+            .doPrivileged(gripper);
 
         gripper.m_system = null;
 
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
index 5052f98..178358b 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
@@ -30,22 +30,23 @@
 import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
 import org.apache.felix.framework.security.util.Permissions;
 import org.apache.felix.framework.security.util.PropertiesCache;
+import org.apache.felix.moduleloader.IContent;
 import org.osgi.framework.Bundle;
 import org.osgi.service.permissionadmin.PermissionAdmin;
 import org.osgi.service.permissionadmin.PermissionInfo;
 
 /**
- * This class is a relatively straight forward implementation of the PermissionAdmin service.
- * The only somewhat involved thing is that it respects the presents of a
- * conditionalpermissionadmin service as per spec.
+ * This class is a relatively straight forward implementation of the
+ * PermissionAdmin service. The only somewhat involved thing is that it respects
+ * the presents of a conditionalpermissionadmin service as per spec.
  */
-// TODO: Do we need this class at all or can we just emulate it using the condpermadmin?
+// TODO: Do we need this class at all or can we just emulate it using the
+// condpermadmin?
 public final class PermissionAdminImpl implements PermissionAdmin
 {
-    private static final PermissionInfo[] ALL_PERMISSION =
-        new PermissionInfo[] { new PermissionInfo(
-            AllPermission.class.getName(), "", "") };
-    
+    private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
+        AllPermission.class.getName(), "", "") };
+
     private final Map m_store = new HashMap();
 
     private final PropertiesCache m_cache;
@@ -59,11 +60,7 @@
     {
         m_permissions = permissions;
         m_cache = cache;
-        Map old = m_cache.read(PermissionInfo[].class);
-        if (old != null)
-        {
-            m_store.putAll(old);
-        }
+        m_cache.read(PermissionInfo[].class, m_store);
     }
 
     public PermissionInfo[] getDefaultPermissions()
@@ -106,71 +103,76 @@
     }
 
     /**
-     * This will do the actual permission check as described in the core spec 10.2
-     * It will respect a present condpermadmin service as described in 9.10.
+     * This will do the actual permission check as described in the core spec
+     * 10.2 It will respect a present condpermadmin service as described in
+     * 9.10.
      * 
-     * @param location the location of the bundle.
-     * @param bundle the bundle in question.
-     * @param permission the permission to check.
-     * @param cpai A condpermadmin if one is present else null.
-     * @param pd the protectiondomain
-     * @return Boolean.TRUE if the location is bound and the permission is 
-     *  granted or if there is no cpa and the default permissions imply the 
-     *  permission Boolean.FALSE otherwise unless the location is not bound and 
-     *  their is a cpa in which case null is returned.
+     * @param location
+     *            the location of the bundle.
+     * @param bundle
+     *            the bundle in question.
+     * @param permission
+     *            the permission to check.
+     * @param cpai
+     *            A condpermadmin if one is present else null.
+     * @param pd
+     *            the protectiondomain
+     * @return Boolean.TRUE if the location is bound and the permission is
+     *         granted or if there is no cpa and the default permissions imply
+     *         the permission Boolean.FALSE otherwise unless the location is not
+     *         bound and their is a cpa in which case null is returned.
      */
     public Boolean hasPermission(String location, Bundle bundle,
         Permission permission, ConditionalPermissionAdminImpl cpai,
-        ProtectionDomain pd)
+        ProtectionDomain pd, IContent content)
     {
         PermissionInfo[] permissions = null;
-        boolean file = false;
+        PermissionInfo[] defaults = null;
+        boolean contains = false;
         synchronized (m_store)
         {
-            if (m_store.containsKey(location))
-            {
-                permissions = (PermissionInfo[]) m_store.get(location);
-                file = true;
-            }
-            else if ((cpai == null) || (cpai.isEmpty()))
-            {
-                if (m_default != null)
-                {
-                    permissions = m_default;
-                }
-                else
-                {
-                    permissions = ALL_PERMISSION;
-                }
-            }
+            contains = m_store.containsKey(location);
+            permissions = (PermissionInfo[]) m_store.get(location);
+            defaults = m_default;
         }
-        if ((cpai == null) || cpai.isEmpty() || file)
+        if (contains)
         {
-            if (check(permissions, permission, file ? bundle : null))
+            if (check(permissions, permission, bundle))
+            {
+                return Boolean.TRUE;
+            }
+            return check(m_permissions.getImplicit(bundle), permission, bundle) ? Boolean.TRUE
+                : Boolean.FALSE;
+        }
+        else if (cpai == null
+            || (cpai.isEmpty() && cpai
+                .impliesLocal(bundle, content, permission)))
+        {
+            if (defaults != null)
+            {
+                if (check(defaults, permission, null))
+                {
+                    return Boolean.TRUE;
+                }
+                return check(m_permissions.getImplicit(bundle), permission,
+                    bundle) ? Boolean.TRUE : Boolean.FALSE;
+            }
+            else
             {
                 return Boolean.TRUE;
             }
         }
-
-        permissions = m_permissions.getImplicit(bundle);
-
-        if (check(permissions, permission, bundle))
-        {
-            return Boolean.TRUE;
-        }
-
-        if ((cpai != null) && !file)
+        else
         {
             return null;
         }
-        return Boolean.FALSE;
     }
 
     private boolean check(PermissionInfo[] permissions, Permission permission,
         Bundle bundle)
     {
-        Permissions permissionsObject =
-            m_permissions.getPermissions(permissions);
+        Permissions permissionsObject = m_permissions
+            .getPermissions(permissions);
 
         return permissionsObject.implies(permission, bundle);
     }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
index 1e3f0cc..2dd3b18 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
@@ -33,27 +33,27 @@
 import org.apache.felix.moduleloader.IContent;
 
 /**
- * This class makes a given content available as a inputstream with a jar content.
- * In other words the stream can be used as input to a JarInputStream. 
+ * This class makes a given content available as a inputstream with a jar
+ * content. In other words the stream can be used as input to a JarInputStream.
  */
 public final class BundleInputStream extends InputStream
 {
     private final IContent m_root;
     private final Enumeration m_content;
     private final OutputStreamBuffer m_outputBuffer = new OutputStreamBuffer();
-    
+
     private ByteArrayInputStream m_buffer = null;
     private JarOutputStream m_output = null;
-    
-    public BundleInputStream(IContent root) throws IOException 
+
+    public BundleInputStream(IContent root) throws IOException
     {
         m_root = root;
-        
+
         List entries = new ArrayList();
-        
+
         int count = 0;
         String manifest = null;
-        for (Enumeration e = m_root.getEntries();e.hasMoreElements();)
+        for (Enumeration e = m_root.getEntries(); e.hasMoreElements();)
         {
             String entry = (String) e.nextElement();
             if (entry.equalsIgnoreCase("META-INF/MANIFEST.MF"))
@@ -77,16 +77,16 @@
             manifest = "META-INF/MANIFEST.MF";
         }
         m_content = new IteratorToEnumeration(entries.iterator());
-        
+
         try
         {
             m_output = new JarOutputStream(m_outputBuffer);
             readNext(manifest);
-            m_buffer = new ByteArrayInputStream(
-                m_outputBuffer.m_outBuffer.toByteArray());
+            m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+                .toByteArray());
 
             m_outputBuffer.m_outBuffer = null;
-        } 
+        }
         catch (IOException ex)
         {
             // TODO: figure out what is wrong
@@ -111,24 +111,24 @@
                 m_buffer = null;
                 return read();
             }
-            
+
             return result;
         }
 
         if (m_content.hasMoreElements())
         {
             String current = (String) m_content.nextElement();
-            
+
             readNext(current);
-            
+
             if (!m_content.hasMoreElements())
             {
                 m_output.close();
                 m_output = null;
             }
 
-            m_buffer = new ByteArrayInputStream(
-                m_outputBuffer.m_outBuffer.toByteArray());
+            m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+                .toByteArray());
 
             m_outputBuffer.m_outBuffer = null;
         }
@@ -149,7 +149,7 @@
             {
                 throw new IOException("Missing entry");
             }
-            
+
             JarEntry entry = new JarEntry(path);
 
             m_output.putNextEntry(entry);
@@ -169,7 +169,7 @@
                 {
                     in.close();
                 }
-                catch (Exception ex) 
+                catch (Exception ex)
                 {
                     // Not much we can do
                 }
@@ -180,7 +180,7 @@
 
         m_output.flush();
     }
-    
+
     private static final class OutputStreamBuffer extends OutputStream
     {
         ByteArrayOutputStream m_outBuffer = null;
@@ -189,12 +189,12 @@
         {
             m_outBuffer.write(b);
         }
-        
+
         public void write(byte[] buffer) throws IOException
         {
             m_outBuffer.write(buffer);
-        }       
-        
+        }
+
         public void write(byte[] buffer, int offset, int length)
         {
             m_outBuffer.write(buffer, offset, length);
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
index ec1375f..1679fe1 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
@@ -18,21 +18,20 @@
  */
 package org.apache.felix.framework.security.util;
 
-import java.util.ArrayList;
+import java.security.Permission;
+import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.WeakHashMap;
-import java.util.Map.Entry;
 
-import org.apache.felix.framework.security.verifier.SignerMatcher;
+import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionInfoImpl;
 import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.moduleloader.IModule;
 import org.osgi.framework.Bundle;
-import org.osgi.service.condpermadmin.BundleSignerCondition;
 import org.osgi.service.condpermadmin.Condition;
 import org.osgi.service.condpermadmin.ConditionInfo;
 
@@ -44,11 +43,11 @@
 public final class Conditions
 {
     private static final ThreadLocal m_conditionStack = new ThreadLocal();
+    private static final Map m_conditionCache = new WeakHashMap();
 
     private final Map m_cache = new WeakHashMap();
-    
-    private final Bundle m_bundle;
-    private final String[] m_signers;
+
+    private final IModule m_module;
 
     private final ConditionInfo[] m_conditionInfos;
     private final Condition[] m_conditions;
@@ -56,21 +55,44 @@
 
     public Conditions(SecureAction action)
     {
-        this(null, null, null, action);
+        this(null, null, action);
     }
-    
-    private Conditions(Bundle bundle, String[] signers,
-        ConditionInfo[] conditions, SecureAction action)
+
+    private Conditions(IModule module, ConditionInfo[] conditionInfos,
+        SecureAction action)
     {
-        m_bundle = bundle;
-        m_signers = signers;
-        m_conditionInfos = conditions;
-        m_conditions = ((conditions != null) && (bundle != null)) ? new Condition[m_conditionInfos.length] : null;
+        m_module = module;
+        m_conditionInfos = conditionInfos;
+        if ((module != null) && (conditionInfos != null))
+        {
+            synchronized (m_conditionCache)
+            {
+                Map conditionMap = (Map) m_conditionCache.get(module);
+                if (conditionMap == null)
+                {
+                    conditionMap = new HashMap();
+                    conditionMap.put(m_conditionInfos,
+                        new Condition[m_conditionInfos.length]);
+                    m_conditionCache.put(module, conditionMap);
+                }
+                Condition[] conditions = (Condition[]) conditionMap
+                    .get(m_conditionInfos);
+                if (conditions == null)
+                {
+                    conditions = new Condition[m_conditionInfos.length];
+                    conditionMap.put(m_conditionInfos, conditions);
+                }
+                m_conditions = conditions;
+            }
+        }
+        else
+        {
+            m_conditions = null;
+        }
         m_action = action;
     }
 
-    public Conditions getConditions(Bundle bundle, String[] signers,
-        ConditionInfo[] conditions)
+    public Conditions getConditions(IModule key, ConditionInfo[] conditions)
     {
         Conditions result = null;
         Map index = null;
@@ -85,90 +107,85 @@
         }
         synchronized (index)
         {
-            if (bundle != null)
+            if (key != null)
             {
-                result = (Conditions) index.get(bundle);
+                result = (Conditions) index.get(key);
             }
         }
-        
+
         if (result == null)
         {
-            result = new Conditions(bundle, signers, conditions, m_action);
+            result = new Conditions(key, conditions, m_action);
             synchronized (index)
             {
-                index.put(bundle, result);
+                index.put(key, result);
             }
         }
-        
+
         return result;
     }
 
     // See whether the given list is satisfied or not
-    public boolean isSatisfied(List posts)
+    public boolean isSatisfied(List posts, Permissions permissions,
+        Permission permission)
     {
-        for (int i = 0; i < m_conditions.length; i++)
+        boolean check = true;
+        for (int i = 0; i < m_conditionInfos.length; i++)
         {
-            if (m_bundle == null)
+            if (m_module == null)
             {
-                if (!m_conditionInfos[i].getType().equals(
-                    BundleSignerCondition.class.getName()))
-                {
-                    return false;
-                }
-                String[] args = m_conditionInfos[i].getArgs();
-
-                boolean match = false;
-                if (args.length == 0)
-                {
-                    for (int j = 0; j < m_signers.length; j++)
-                    {
-                        if (SignerMatcher.match(args[0], m_signers[j]))
-                        {
-                            match = true;
-                            break;
-                        }
-                    }
-                }
-                if (!match)
-                {
-                    return false;
-                }
-                continue;
+                // TODO: check whether this is correct!
+                break;
             }
             try
             {
                 Condition condition = null;
                 boolean add = false;
                 Class clazz = Class.forName(m_conditionInfos[i].getType());
-                
-                synchronized (m_conditionInfos)
+
+                synchronized (m_conditions)
                 {
+                    if (m_conditions[i] == null)
+                    {
+                        m_conditions[i] = createCondition(m_module.getBundle(),
+                            clazz, m_conditionInfos[i]);
+                    }
                     condition = m_conditions[i];
                 }
-                
-                if (condition == null)
+
+                Object current = m_conditionStack.get();
+                if (current != null)
                 {
-                    add = true;
-                    condition = createCondition(m_bundle, clazz, m_conditionInfos[i]);
-                }
-                
-                if (condition.isPostponed())
-                {
-                    posts.add(condition);
-                    if (add)
+                    if (current instanceof HashSet)
                     {
-                        synchronized (m_conditionInfos)
+                        if (((HashSet) current).contains(clazz))
                         {
-                            if (m_conditions[i] == null)
-                            {
-                                m_conditions[i] = condition;
-                            }
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (current == clazz)
+                        {
+                            return false;
                         }
                     }
                 }
+
+                if (condition.isPostponed())
+                {
+                    if (check && !permissions.implies(permission, null))
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        check = false;
+                    }
+                    posts.add(new Object[] { condition, new Integer(i) });
+                }
                 else
                 {
-                    Object current = m_conditionStack.get();
 
                     if (current == null)
                     {
@@ -199,20 +216,16 @@
                     }
                     try
                     {
+                        boolean mutable = condition.isMutable();
                         boolean result = condition.isSatisfied();
 
-                        if (!condition.isMutable() && ((condition != Condition.TRUE) && (condition != Condition.FALSE)))
+                        if (!mutable
+                            && ((condition != Condition.TRUE) && (condition != Condition.FALSE)))
                         {
-                            synchronized (m_conditionInfos)
+                            synchronized (m_conditions)
                             {
-                                m_conditions[i] = result ? Condition.TRUE : Condition.FALSE;
-                            }
-                        }
-                        else
-                        {
-                            synchronized (m_conditionInfos)
-                            {
-                                m_conditions[i] = condition;
+                                m_conditions[i] = result ? Condition.TRUE
+                                    : Condition.FALSE;
                             }
                         }
                         if (!result)
@@ -249,121 +262,99 @@
 
     public boolean evalRecursive(List entries)
     {
-        return _evalRecursive(entries, 0, new ArrayList(), new HashMap());
-    }
-
-    private boolean _evalRecursive(List entries, int pos, List acc, Map contexts)
-    {
-        if (pos == entries.size())
+        Map contexts = new HashMap();
+        outer: for (Iterator iter = entries.iterator(); iter.hasNext();)
         {
-            // we need to group by type by tuple
-            Map conditions = new HashMap();
-            for (Iterator iter = acc.iterator(); iter.hasNext();)
+            List tuples = (List) iter.next();
+            inner: for (Iterator inner = tuples.iterator(); inner.hasNext();)
             {
-                for (Iterator iter2 = ((List) iter.next()).iterator(); iter2
-                    .hasNext();)
+                Object[] entry = (Object[]) inner.next();
+                List conditions = (List) entry[1];
+                if (conditions == null)
                 {
-                    Object entry = iter2.next();
-                    Set group = (Set) conditions.get(entry.getClass());
-
-                    if (group == null)
-                    {
-                        group = new HashSet();
-                    }
-                    group.add(entry);
-
-                    conditions.put(entry.getClass(), group);
-                }
-            }
-
-            // and then eval per group
-            for (Iterator iter = conditions.entrySet().iterator(); iter.hasNext();)
-            {
-                Entry entry = (Entry) iter.next();
-                Class key = (Class) entry.getKey();
-                
-                Hashtable context = (Hashtable) contexts.get(key);
-                if (context == null)
-                {
-                    context = new Hashtable();
-                    contexts.put(key, context);
-                }
-                Set set = (Set) entry.getValue();
-                Condition[] current =
-                    (Condition[]) set.toArray(new Condition[set.size()]);
-
-                // We must be catching recursive evaluation as per spec, hence use a thread
-                // local stack to do so
-                Object currentCond = m_conditionStack.get();
-
-                if (currentCond == null)
-                {
-                    m_conditionStack.set(key);
-                }
-                else
-                {
-                    if (currentCond instanceof HashSet)
-                    {
-                        if (((HashSet) currentCond).contains(key))
-                        {
-                            return false;
-                        }
-                        ((HashSet) currentCond).add(key);
-                    }
-                    else
-                    {
-                        if (currentCond == key)
-                        {
-                            return false;
-                        }
-                        HashSet frame = new HashSet();
-                        frame.add(current);
-                        frame.add(key);
-                        m_conditionStack.set(frame);
-                        currentCond = frame;
-                    }
-                }
-                try
-                {
-                    if (!current[0].isSatisfied(current, context))
+                    if (!((ConditionalPermissionInfoImpl) entry[0]).isAllow())
                     {
                         return false;
                     }
+                    continue outer;
                 }
-                finally
+                for (Iterator iter2 = conditions.iterator(); iter2.hasNext();)
                 {
-                    if (currentCond == null)
+                    Object[] condEntry = (Object[]) iter2.next();
+                    Condition cond = (Condition) condEntry[0];
+                    Dictionary context = (Dictionary) contexts.get(cond
+                        .getClass());
+                    if (context == null)
                     {
-                        m_conditionStack.set(null);
+                        context = new Hashtable();
+                        contexts.put(cond.getClass(), context);
+                    }
+                    Object current = m_conditionStack.get();
+                    if (current == null)
+                    {
+                        m_conditionStack.set(cond.getClass());
                     }
                     else
                     {
-                        ((HashSet) currentCond).remove(key);
-                        if (((HashSet) currentCond).isEmpty())
+                        if (current instanceof HashSet)
+                        {
+                            ((HashSet) current).add(cond.getClass());
+                        }
+                        else
+                        {
+                            HashSet frame = new HashSet();
+                            frame.add(current);
+                            frame.add(cond.getClass());
+                            m_conditionStack.set(frame);
+                            current = frame;
+                        }
+                    }
+                    boolean result;
+                    boolean mutable = cond.isMutable();
+                    try
+                    {
+                        result = cond.isSatisfied(new Condition[] { cond },
+                            context);
+                    }
+                    finally
+                    {
+                        if (current == null)
                         {
                             m_conditionStack.set(null);
                         }
+                        else
+                        {
+                            ((HashSet) current).remove(cond.getClass());
+                            if (((HashSet) current).isEmpty())
+                            {
+                                m_conditionStack.set(null);
+                            }
+                        }
+                    }
+                    if (!mutable && (cond != Condition.TRUE)
+                        && (cond != Condition.FALSE))
+                    {
+                        synchronized (((Conditions) entry[2]).m_conditions)
+                        {
+                            ((Conditions) entry[2]).m_conditions[((Integer) condEntry[1])
+                                .intValue()] = result ? Condition.TRUE
+                                : Condition.FALSE;
+                        }
+                    }
+                    if (!result)
+                    {
+                        continue inner;
                     }
                 }
+                if (!((ConditionalPermissionInfoImpl) entry[0]).isAllow())
+                {
+                    return false;
+                }
+                continue outer;
             }
-            return true;
+            return false;
         }
-
-        List entry = (List) entries.get(pos);
-
-        for (int i = 0; i < entry.size(); i++)
-        {
-            acc.add(entry.get(i));
-
-            if (_evalRecursive(entries, pos + 1, acc, contexts))
-            {
-                return true;
-            }
-
-            acc.remove(acc.size() - 1);
-        }
-
-        return false;
+        return true;
     }
 
     private Condition createCondition(final Bundle bundle, final Class clazz,
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
index 5f31205..a926338 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
@@ -25,13 +25,9 @@
 import java.security.AllPermission;
 import java.security.Permission;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.WeakHashMap;
 
-import org.apache.felix.framework.security.util.Permissions;
-import org.apache.felix.framework.security.util.PropertiesCache;
 import org.apache.felix.moduleloader.IContent;
 import org.osgi.framework.Bundle;
 import org.osgi.service.permissionadmin.PermissionInfo;
@@ -43,31 +39,15 @@
 // TODO: maybe use bundle events to clean thing up or weak/soft references
 public final class LocalPermissions
 {
-    private static final PermissionInfo[] ALL_PERMISSION =
-        new PermissionInfo[] { new PermissionInfo(
-            AllPermission.class.getName(), "", "") };
-    
-    private final Map m_cache = new HashMap();
+    private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
+        AllPermission.class.getName(), "", "") };
+
+    private final Map m_cache = new WeakHashMap();
     private final Permissions m_permissions;
 
-    public LocalPermissions(Permissions permissions, PropertiesCache cache)
-        throws IOException
+    public LocalPermissions(Permissions permissions) throws IOException
     {
         m_permissions = permissions;
-        for (Iterator iter =
-            cache.read(PermissionInfo[].class).entrySet().iterator(); iter
-            .hasNext();)
-        {
-            Entry entry = (Entry) iter.next();
-            PermissionInfo[] value = (PermissionInfo[]) entry.getValue();
-            if ((value.length == 1)
-                && (AllPermission.class.getName().equals(value[0].getType())))
-            {
-                value = ALL_PERMISSION;
-            }
-
-            m_cache.put(entry.getKey(), value);
-        }
     }
 
     /**
@@ -75,20 +55,24 @@
      * permissions of the given bundle or if there are none otherwise, false.
      * See core spec 9.2.1.
      * 
-     * @param root the root to use for cacheing as a key
-     * @param loader the loader to get the content of the bundle from
-     * @param bundle the bundle in quesiton
-     * @param permission the permission to check
+     * @param root
+     *            the root to use for cacheing as a key
+     * @param loader
+     *            the loader to get the content of the bundle from
+     * @param bundle
+     *            the bundle in quesiton
+     * @param permission
+     *            the permission to check
      * @return true if implied by local permissions.
      */
-    public boolean implies(String root, IContent content, Bundle bundle,
+    public boolean implies(IContent content, Bundle bundle,
         Permission permission)
     {
         PermissionInfo[] permissions = null;
 
         synchronized (m_cache)
         {
-            if (!m_cache.containsKey(root))
+            if (!m_cache.containsKey(content))
             {
                 InputStream in = null;
                 try
@@ -98,28 +82,26 @@
                     {
                         ArrayList perms = new ArrayList();
 
-                        BufferedReader reader =
-                            new BufferedReader(new InputStreamReader(in,
-                                "UTF-8"));
-                        for (String line = reader.readLine(); line != null; line =
-                            reader.readLine())
+                        BufferedReader reader = new BufferedReader(
+                            new InputStreamReader(in, "UTF-8"));
+                        for (String line = reader.readLine(); line != null; line = reader
+                            .readLine())
                         {
                             String trim = line.trim();
-                            if (trim.startsWith("#") || trim.startsWith("//"))
+                            if (trim.startsWith("#") || trim.startsWith("//")
+                                || (trim.length() == 0))
                             {
                                 continue;
                             }
                             perms.add(new PermissionInfo(line));
                         }
 
-                        permissions =
-                            (PermissionInfo[]) perms
-                                .toArray(new PermissionInfo[perms.size()]);
+                        permissions = (PermissionInfo[]) perms
+                            .toArray(new PermissionInfo[perms.size()]);
                     }
                 }
                 catch (Exception ex)
                 {
-                    ex.printStackTrace();
                 }
                 finally
                 {
@@ -142,23 +124,15 @@
                     permissions = ALL_PERMISSION;
                 }
 
-                m_cache.put(root, permissions);
+                m_cache.put(content, permissions);
             }
             else
             {
-                permissions = (PermissionInfo[]) m_cache.get(root);
+                permissions = (PermissionInfo[]) m_cache.get(content);
             }
         }
 
         return m_permissions.getPermissions(permissions).implies(permission,
             bundle);
     }
-
-    public Map getStore() 
-    {
-        synchronized (m_cache)
-        {
-            return new HashMap(m_cache);
-        }
-    }
 }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
index 5ce3ca5..5d885cf 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
@@ -23,10 +23,11 @@
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
+import java.security.AccessController;
 import java.security.AllPermission;
 import java.security.Permission;
 import java.security.PermissionCollection;
-import java.security.*;
+import java.security.PrivilegedAction;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -44,19 +45,18 @@
 import org.osgi.service.permissionadmin.PermissionInfo;
 
 /**
- * A permission cache that uses permisssion infos as keys. Permission are created
- * from the parent classloader or any exported package. 
+ * A permission cache that uses permisssion infos as keys. Permission are
+ * created from the parent classloader or any exported package.
  */
 // TODO: maybe use bundle events instead of soft/weak references
 public final class Permissions
 {
-    private static final ClassLoader m_classLoader =
-        Permissions.class.getClassLoader();
+    private static final ClassLoader m_classLoader = Permissions.class
+        .getClassLoader();
 
     private static final Map m_permissionCache = new HashMap();
     private static final Map m_permissions = new HashMap();
-    private static final ReferenceQueue m_permissionsQueue =
-        new ReferenceQueue();
+    private static final ReferenceQueue m_permissionsQueue = new ReferenceQueue();
 
     private static final ThreadLocal m_stack = new ThreadLocal();
 
@@ -69,9 +69,8 @@
 
     public static final AllPermission ALL_PERMISSION = new AllPermission();
 
-    private static final PermissionInfo[] IMPLICIT =
-        new PermissionInfo[] { new PermissionInfo(FilePermission.class
-            .getName(), "-", "read,write,delete") };
+    private static final PermissionInfo[] IMPLICIT = new PermissionInfo[] { new PermissionInfo(
+        FilePermission.class.getName(), "-", "read,write,delete") };
 
     Permissions(PermissionInfo[] permissionInfos, BundleContext context,
         SecureAction action)
@@ -102,13 +101,17 @@
         m_allPermission = true;
         m_action = action;
     }
-    
+
     public PermissionInfo[] getImplicit(Bundle bundle)
     {
         return new PermissionInfo[] {
             IMPLICIT[0],
             new PermissionInfo(AdminPermission.class.getName(), "(id="
-                + bundle.getBundleId() + ")", AdminPermission.METADATA) };
+                + bundle.getBundleId() + ")", AdminPermission.METADATA),
+            new PermissionInfo(AdminPermission.class.getName(), "(id="
+                + bundle.getBundleId() + ")", AdminPermission.RESOURCE),
+            new PermissionInfo(AdminPermission.class.getName(), "(id="
+                + bundle.getBundleId() + ")", AdminPermission.CONTEXT) };
     }
 
     public Permissions getPermissions(PermissionInfo[] permissionInfos)
@@ -177,11 +180,11 @@
                 return false;
             }
 
-            if (o instanceof Entry) 
+            if (o instanceof Entry)
             {
-                return entry.equals(((Entry)o).get());
-            } 
-            else 
+                return entry.equals(((Entry) o).get());
+            }
+            else
             {
                 return false;
             }
@@ -237,8 +240,8 @@
 
     private void cleanUp(ReferenceQueue queue, Map cache)
     {
-        for (Entry entry = (Entry) queue.poll(); entry != null; entry =
-            (Entry) queue.poll())
+        for (Entry entry = (Entry) queue.poll(); entry != null; entry = (Entry) queue
+            .poll())
         {
             synchronized (cache)
             {
@@ -248,12 +251,14 @@
     }
 
     /**
-     * @param target the permission to be implied
-     * @param bundle if not null then allow implicit permissions like file 
-     *     access to local data area
+     * @param target
+     *            the permission to be implied
+     * @param bundle
+     *            if not null then allow implicit permissions like file access
+     *            to local data area
      * @return true if the permission is implied by this permissions object.
      */
-    public boolean implies(Permission target, Bundle bundle)
+    public boolean implies(Permission target, final Bundle bundle)
     {
         if (m_allPermission)
         {
@@ -273,7 +278,7 @@
                 {
                     String postfix = "";
                     String name = m_permissionInfos[i].getName();
-                    if (!"<<ALL FILES>>".equals(name)) 
+                    if (!"<<ALL FILES>>".equals(name))
                     {
                         if (name.endsWith("*") || name.endsWith("-"))
                         {
@@ -282,13 +287,20 @@
                         }
                         if (!(new File(name)).isAbsolute())
                         {
-                            BundleContext context = bundle.getBundleContext();
+                            BundleContext context = (BundleContext) AccessController
+                                .doPrivileged(new PrivilegedAction()
+                                {
+                                    public Object run()
+                                    {
+                                        return bundle.getBundleContext();
+                                    }
+                                });
                             if (context == null)
                             {
                                 break;
                             }
-                            name =
-                                m_action.getAbsolutePath(new File(context.getDataFile(""), name));
+                            name = m_action.getAbsolutePath(new File(context
+                                .getDataFile(""), name));
                         }
                         if (postfix.length() > 0)
                         {
@@ -302,10 +314,54 @@
                             }
                         }
                     }
-                    return createPermission(
+                    Permission source = createPermission(new PermissionInfo(
+                        FilePermission.class.getName(), name,
+                        m_permissionInfos[i].getActions()), targetClass);
+                    postfix = "";
+                    name = target.getName();
+                    if (!"<<ALL FILES>>".equals(name))
+                    {
+                        if (name.endsWith("*") || name.endsWith("-"))
+                        {
+                            postfix = name.substring(name.length() - 1);
+                            name = name.substring(0, name.length() - 1);
+                        }
+                        if (!(new File(name)).isAbsolute())
+                        {
+                            BundleContext context = (BundleContext) AccessController
+                                .doPrivileged(new PrivilegedAction()
+                                {
+                                    public Object run()
+                                    {
+                                        return bundle.getBundleContext();
+                                    }
+                                });
+                            if (context == null)
+                            {
+                                break;
+                            }
+                            name = m_action.getAbsolutePath(new File(context
+                                .getDataFile(""), name));
+                        }
+                        if (postfix.length() > 0)
+                        {
+                            if ((name.length() > 0) && !name.endsWith("/"))
+                            {
+                                name += "/" + postfix;
+                            }
+                            else
+                            {
+                                name += postfix;
+                            }
+                        }
+                    }
+                    Permission realTarget = createPermission(
                         new PermissionInfo(FilePermission.class.getName(),
-                            name, m_permissionInfos[i].getActions()),
-                        targetClass).implies(target);
+                            name, target.getActions()), targetClass);
+                    if (source.implies(realTarget))
+                    {
+                        return true;
+                    }
                 }
             }
             return false;
@@ -374,8 +430,8 @@
 
                     if (infoType.equals(permissionType))
                     {
-                        Permission permission =
-                            createPermission(permissionInfo, targetClass);
+                        Permission permission = createPermission(
+                            permissionInfo, targetClass);
 
                         if (permission != null)
                         {
@@ -478,86 +534,94 @@
     private Permission createPermission(final PermissionInfo permissionInfo,
         final Class target)
     {
-        return (Permission) AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run()
+        return (Permission) AccessController
+            .doPrivileged(new PrivilegedAction()
             {
-        Permission cached = getFromCache(permissionInfo.getEncoded(), target);
-
-        if (cached != null)
-        {
-            return cached;
-        }
-
-        try
-        {
-            if (m_classLoader.loadClass(target.getName()) == target)
-            {
-                return addToCache(permissionInfo.getEncoded(),
-                    createPermission(permissionInfo.getName(), permissionInfo
-                        .getActions(), target));
-            }
-        }
-        catch (ClassNotFoundException e1)
-        {
-        }
-
-        ServiceReference[] refs = null;
-        try
-        {
-            refs =
-                m_context.getServiceReferences(PackageAdmin.class.getName(),
-                    null);
-        }
-        catch (InvalidSyntaxException e)
-        {
-        }
-        if (refs != null)
-        {
-            for (int i = 0; i < refs.length; i++)
-            {
-                PackageAdmin admin =
-                    (PackageAdmin) m_context.getService(refs[i]);
-
-                if (admin != null)
+                public Object run()
                 {
-                    Permission result = null;
-                    Bundle bundle = admin.getBundle(target);
-                    if (bundle != null)
-                    {
-                        ExportedPackage[] exports =
-                            admin.getExportedPackages(bundle);
-                        if (exports != null)
-                        {
-                            String name = target.getName();
-                            name = name.substring(0, name.lastIndexOf('.'));
+                    Permission cached = getFromCache(permissionInfo
+                        .getEncoded(), target);
 
-                            for (int j = 0; j < exports.length; j++)
+                    if (cached != null)
+                    {
+                        return cached;
+                    }
+
+                    try
+                    {
+                        if (m_classLoader.loadClass(target.getName()) == target)
+                        {
+                            return addToCache(permissionInfo.getEncoded(),
+                                createPermission(permissionInfo.getName(),
+                                    permissionInfo.getActions(), target));
+                        }
+                    }
+                    catch (ClassNotFoundException e1)
+                    {
+                    }
+
+                    ServiceReference[] refs = null;
+                    try
+                    {
+                        refs = m_context.getServiceReferences(
+                            PackageAdmin.class.getName(), null);
+                    }
+                    catch (InvalidSyntaxException e)
+                    {
+                    }
+                    if (refs != null)
+                    {
+                        for (int i = 0; i < refs.length; i++)
+                        {
+                            PackageAdmin admin = (PackageAdmin) m_context
+                                .getService(refs[i]);
+
+                            if (admin != null)
                             {
-                                if (exports[j].getName().equals(name))
+                                Permission result = null;
+                                Bundle bundle = admin.getBundle(target);
+                                if (bundle != null)
                                 {
-                                    result =
-                                        createPermission(permissionInfo
-                                            .getName(), permissionInfo
-                                            .getActions(), target);
-                                    break;
+                                    ExportedPackage[] exports = admin
+                                        .getExportedPackages(bundle);
+                                    if (exports != null)
+                                    {
+                                        String name = target.getName();
+                                        name = name.substring(0, name
+                                            .lastIndexOf('.'));
+
+                                        for (int j = 0; j < exports.length; j++)
+                                        {
+                                            if (exports[j].getName().equals(
+                                                name))
+                                            {
+                                                result = createPermission(
+                                                    permissionInfo.getName(),
+                                                    permissionInfo.getActions(),
+                                                    target);
+                                                break;
+                                            }
+                                        }
+                                    }
                                 }
+
+                                m_context.ungetService(refs[i]);
+
+                                return addToCache(permissionInfo.getEncoded(),
+                                    result);
                             }
                         }
                     }
 
-                    m_context.ungetService(refs[i]);
-
-                    return addToCache(permissionInfo.getEncoded(), result);
+                    return null;
                 }
-            }
-        }
-
-        return null;
-        }});
+            });
     }
 
     private Permission createPermission(String name, String action, Class target)
     {
+        // System.out.println("\n\n|" + name + "|\n--\n|" + action + "|\n--\n" +
+        // target + "\n\n");
         try
         {
             return (Permission) m_action.getConstructor(target,
@@ -566,7 +630,7 @@
         }
         catch (Exception ex)
         {
-            ex.printStackTrace();
+            // TODO: log this or something
         }
 
         return null;
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
index c00bb8c..6c76d39 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
@@ -26,10 +26,10 @@
 import java.io.OutputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
+import java.util.TreeMap;
 import java.util.Map.Entry;
 
 import org.apache.felix.framework.util.SecureAction;
@@ -66,11 +66,13 @@
 
                 Properties store = new Properties();
 
+                int count = 0;
+
                 for (Iterator iter = data.entrySet().iterator(); iter.hasNext();)
                 {
                     Entry entry = (Entry) iter.next();
-                    store.setProperty((String) entry.getKey(), getEncoded(entry
-                        .getValue()));
+                    store.setProperty(count++ + "-" + (String) entry.getKey(),
+                        getEncoded(entry.getValue()));
                 }
 
                 store.store(out, null);
@@ -126,15 +128,15 @@
         }
     }
 
-    public Map read(Class target) throws IOException
+    public void read(Class target, Map map) throws IOException
     {
         if (!m_file.isFile())
         {
-            return null;
+            return;
         }
         InputStream in = null;
         Exception other = null;
-        Map result = new HashMap();
+        Map result = new TreeMap();
         try
         {
             in = m_action.getFileInputStream(m_file);
@@ -171,7 +173,12 @@
                 }
             }
         }
-        return result;
+        for (Iterator iter = result.entrySet().iterator(); iter.hasNext();)
+        {
+            Entry entry = (Entry) iter.next();
+            String key = (String) entry.getKey();
+            map.put(key.substring(key.indexOf("-")), entry.getValue());
+        }
     }
 
     private String getEncoded(Object target) throws IOException
@@ -204,26 +211,25 @@
                 Properties props = new Properties();
                 props.load(new ByteArrayInputStream(encoded.getBytes()));
                 Class componentType = target.getComponentType();
-                Constructor constructor =
-                    m_action.getConstructor(componentType,
-                        new Class[] { String.class });
+                Constructor constructor = m_action.getConstructor(
+                    componentType, new Class[] { String.class });
                 Object[] params = new Object[1];
-                Object[] result =
-                    (Object[]) Array.newInstance(componentType, props.size());
+                Object[] result = (Object[]) Array.newInstance(componentType,
+                    props.size());
 
                 for (Iterator iter = props.entrySet().iterator(); iter
                     .hasNext();)
                 {
                     Entry entry = (Entry) iter.next();
                     params[0] = entry.getValue();
-                    result[Integer.parseInt((String) entry.getKey())] =
-                        constructor.newInstance(params);
+                    result[Integer.parseInt((String) entry.getKey())] = constructor
+                        .newInstance(params);
                 }
 
                 return result;
             }
 
-            return m_action.invoke(m_action.getConstructor(target, 
+            return m_action.invoke(m_action.getConstructor(target,
                 new Class[] { String.class }), new Object[] { encoded });
         }
         catch (Exception ex)
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
index 7425de5..4633cb0 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
@@ -78,19 +78,17 @@
 
         if (m_crlList.trim().length() != 0)
         {
-            CertificateFactory fac =
-                CertificateFactory.getInstance("X509");
-            
+            CertificateFactory fac = CertificateFactory.getInstance("X509");
+
             for (StringTokenizer tok = new StringTokenizer(m_crlList, "|"); tok
                 .hasMoreElements();)
             {
                 InputStream input = null;
                 try
                 {
-                    input =
-                        m_action.getURLConnectionInputStream(m_action
-                            .createURL(null, tok.nextToken(), null)
-                            .openConnection());
+                    input = m_action.getURLConnectionInputStream(m_action
+                        .createURL(null, tok.nextToken(), null)
+                        .openConnection());
                     result.addAll(fac.generateCRLs(input));
                 }
                 catch (Exception ex)
@@ -137,20 +135,18 @@
                 InputStream input = null;
                 try
                 {
-                    input =
-                        m_action.getURLConnectionInputStream(m_action
-                            .createURL(null, storeTok.nextToken().trim(), null)
-                            .openConnection());
+                    input = m_action.getURLConnectionInputStream(m_action
+                        .createURL(null, storeTok.nextToken().trim(), null)
+                        .openConnection());
+                    String pass = passwdTok.nextToken().trim();
 
-                    ks.load(input, passwdTok.nextToken().trim().toCharArray());
+                    ks.load(input, (pass.length() > 0) ? pass.toCharArray()
+                        : null);
 
                     for (Enumeration e = ks.aliases(); e.hasMoreElements();)
                     {
                         String alias = (String) e.nextElement();
-                        if (ks.isCertificateEntry(alias))
-                        {
-                            result.add(ks.getCertificate(alias));
-                        }
+                        result.add(ks.getCertificate(alias));
                     }
                 }
                 catch (Exception ex)
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java b/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
index ef9f5d4..e237f61 100644
--- a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
+++ b/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
@@ -30,13 +30,15 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 
-import org.apache.felix.framework.cache.BundleRevision;
 import org.apache.felix.framework.security.util.BundleInputStream;
 import org.apache.felix.framework.security.util.TrustManager;
 import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IModule;
+import org.osgi.framework.Bundle;
 
 public final class BundleDNParser
 {
@@ -51,15 +53,12 @@
         Method getCertificates = null;
         try
         {
-            getCodeSigners =
-                Class.forName("java.util.jar.JarEntry").getMethod(
-                    "getCodeSigners", null);
-            getSignerCertPath =
-                Class.forName("java.security.CodeSigner").getMethod(
-                    "getSignerCertPath", null);
-            getCertificates =
-                Class.forName("java.security.cert.CertPath").getMethod(
-                    "getCertificates", null);
+            getCodeSigners = Class.forName("java.util.jar.JarEntry").getMethod(
+                "getCodeSigners", null);
+            getSignerCertPath = Class.forName("java.security.CodeSigner")
+                .getMethod("getSignerCertPath", null);
+            getCertificates = Class.forName("java.security.cert.CertPath")
+                .getMethod("getCertificates", null);
         }
         catch (Exception ex)
         {
@@ -73,7 +72,9 @@
         m_getCertificates = getCertificates;
     }
 
-    private final Map m_cache = new HashMap();
+    private final Map m_cache = new WeakHashMap();
+    private final Map m_allCache = new WeakHashMap();
+
     private final TrustManager m_manager;
 
     public BundleDNParser(TrustManager manager)
@@ -89,7 +90,7 @@
         }
     }
 
-    public void put(String root, String[] dnChains)
+    public void put(String root, X509Certificate[] dnChains)
     {
         synchronized (m_cache)
         {
@@ -97,35 +98,65 @@
         }
     }
 
-    public void checkDNChains(String root, IContent content) throws Exception
+    public void checkDNChains(IModule root, IContent content, int signersType)
+        throws Exception
     {
-        synchronized (m_cache)
+        if (signersType == Bundle.SIGNERS_TRUSTED)
         {
-            if (m_cache.containsKey(root))
+            synchronized (m_cache)
             {
-                String[] result = (String[]) m_cache.get(root);
-                if ((result != null) && (result.length == 0))
+                if (m_cache.containsKey(root))
                 {
-                    throw new IOException("Bundle not properly signed");
+                    Map result = (Map) m_cache.get(root);
+                    if ((result != null) && (result.isEmpty()))
+                    {
+                        throw new IOException("Bundle not properly signed");
+                    }
+                    return;
                 }
-                return;
+            }
+        }
+        else
+        {
+            synchronized (m_allCache)
+            {
+                if (m_allCache.containsKey(root))
+                {
+                    Map result = (Map) m_allCache.get(root);
+                    if ((result != null) && (result.isEmpty()))
+                    {
+                        throw new IOException("Bundle not properly signed");
+                    }
+                    return;
+                }
             }
         }
 
-        String[] result = new String[0];
+        Map result = null;
         Exception org = null;
         try
         {
-            result = _getDNChains(root, content);
+            result = _getDNChains(content,
+                signersType == Bundle.SIGNERS_TRUSTED);
         }
         catch (Exception ex)
         {
             org = ex;
         }
 
-        synchronized (m_cache)
+        if (signersType == Bundle.SIGNERS_TRUSTED)
         {
-            m_cache.put(root, result);
+            synchronized (m_cache)
+            {
+                m_cache.put(root, result);
+            }
+        }
+        else
+        {
+            synchronized (m_allCache)
+            {
+                m_allCache.put(root, result);
+            }
         }
 
         if (org != null)
@@ -134,46 +165,70 @@
         }
     }
 
-    public String[] getDNChains(String root, IContent bundleRevision)
+    public Map getDNChains(IModule root, IContent bundleRevision,
+        int signersType)
     {
-        synchronized (m_cache)
+        if (signersType == Bundle.SIGNERS_TRUSTED)
         {
-            if (m_cache.containsKey(root))
+            synchronized (m_cache)
             {
-                String[] result = (String[]) m_cache.get(root);
-                if ((result != null) && (result.length == 0))
+                if (m_cache.containsKey(root))
                 {
-                    return null;
+                    Map result = (Map) m_cache.get(root);
+                    return (result == null) ? new HashMap() : new HashMap(
+                        result);
                 }
-                return result;
+            }
+        }
+        else
+        {
+            synchronized (m_allCache)
+            {
+                if (m_allCache.containsKey(root))
+                {
+                    Map result = (Map) m_allCache.get(root);
+                    return (result == null) ? new HashMap() : new HashMap(
+                        result);
+                }
             }
         }
 
-        String[] result = new String[0];
-        
+        Map result = null;
+
         try
         {
-            result = _getDNChains(root, bundleRevision);
+            result = _getDNChains(bundleRevision,
+                signersType == Bundle.SIGNERS_TRUSTED);
         }
         catch (Exception ex)
         {
             // Ignore
         }
 
-        synchronized (m_cache)
+        if (signersType == Bundle.SIGNERS_TRUSTED)
         {
-            m_cache.put(root, result);
+            synchronized (m_cache)
+            {
+                m_cache.put(root, result);
+            }
+        }
+        else
+        {
+            synchronized (m_allCache)
+            {
+                m_allCache.put(root, result);
+            }
         }
 
-        return result;
-    } 
+        return (result == null) ? new HashMap() : new HashMap(result);
+    }
 
-    private String[] _getDNChains(String root, IContent content)
+    private Map _getDNChains(IContent content, boolean check)
         throws IOException
     {
         X509Certificate[] certificates = null;
 
-        certificates = getCertificates(new BundleInputStream(content));
+        certificates = getCertificates(new BundleInputStream(content), check);
 
         if (certificates == null)
         {
@@ -182,11 +237,9 @@
 
         List rootChains = new ArrayList();
 
-        getRootChains(certificates, rootChains);
+        getRootChains(certificates, rootChains, check);
 
-        List result = new ArrayList();
-
-        SubjectDNParser parser = new SubjectDNParser();
+        Map result = new HashMap();
 
         for (Iterator rootIter = rootChains.iterator(); rootIter.hasNext();)
         {
@@ -198,42 +251,18 @@
 
             X509Certificate current = (X509Certificate) iter.next();
 
-            try
-            {
-                buffer.append(parser
-                    .parseSubjectDN(current.getTBSCertificate()));
-
-                while (iter.hasNext())
-                {
-                    buffer.append(';');
-
-                    current = (X509Certificate) iter.next();
-
-                    buffer.append(parser.parseSubjectDN(current
-                        .getTBSCertificate()));
-                }
-
-                result.add(buffer.toString());
-
-            }
-            catch (Exception ex)
-            {
-                // something went wrong during parsing -
-                // it might be that the cert contained an unsupported OID
-                // TODO: log this or something
-                ex.printStackTrace();
-            }
+            result.put(current, chain);
         }
 
         if (!result.isEmpty())
         {
-            return (String[]) result.toArray(new String[result.size()]);
+            return result;
         }
 
         throw new IOException();
     }
 
-    private X509Certificate[] getCertificates(InputStream input)
+    private X509Certificate[] getCertificates(InputStream input, boolean check)
         throws IOException
     {
         JarInputStream bundle = new JarInputStream(input, true);
@@ -250,9 +279,9 @@
         // This is tricky: jdk1.3 doesn't say anything about what is happening
         // if a bad sig is detected on an entry - later jdk's do say that they
         // will throw a security Exception. The below should cater for both
-        // behaviors. 
-        for (JarEntry entry = bundle.getNextJarEntry(); entry != null; entry =
-            bundle.getNextJarEntry())
+        // behaviors.
+        for (JarEntry entry = bundle.getNextJarEntry(); entry != null; entry = bundle
+            .getNextJarEntry())
         {
 
             if (entry.isDirectory() || entry.getName().startsWith("META-INF"))
@@ -277,8 +306,8 @@
             {
                 try
                 {
-                    Object[] signers =
-                        (Object[]) m_getCodeSigners.invoke(entry, null);
+                    Object[] signers = (Object[]) m_getCodeSigners.invoke(
+                        entry, null);
 
                     if (signers != null)
                     {
@@ -286,16 +315,15 @@
 
                         for (int i = 0; i < signers.length; i++)
                         {
-                            Object path =
-                                m_getSignerCertPath.invoke(signers[i], null);
+                            Object path = m_getSignerCertPath.invoke(
+                                signers[i], null);
 
                             certChains.addAll((List) m_getCertificates.invoke(
                                 path, null));
                         }
 
-                        certificates =
-                            (Certificate[]) certChains
-                                .toArray(new Certificate[certChains.size()]);
+                        certificates = (Certificate[]) certChains
+                            .toArray(new Certificate[certChains.size()]);
                     }
                 }
                 catch (Exception ex)
@@ -312,7 +340,7 @@
 
             List chains = new ArrayList();
 
-            getRootChains(certificates, chains);
+            getRootChains(certificates, chains, check);
 
             if (certificateChains.isEmpty())
             {
@@ -324,13 +352,13 @@
                 for (Iterator iter2 = certificateChains.iterator(); iter2
                     .hasNext();)
                 {
-                    X509Certificate cert =
-                        (X509Certificate) ((List) iter2.next()).get(0);
+                    X509Certificate cert = (X509Certificate) ((List) iter2
+                        .next()).get(0);
                     boolean found = false;
                     for (Iterator iter3 = chains.iterator(); iter3.hasNext();)
                     {
-                        X509Certificate cert2 =
-                            (X509Certificate) ((List) iter3.next()).get(0);
+                        X509Certificate cert2 = (X509Certificate) ((List) iter3
+                            .next()).get(0);
 
                         if (cert.getSubjectDN().equals(cert2.getSubjectDN())
                             && cert.equals(cert2))
@@ -380,7 +408,8 @@
         return false;
     }
 
-    private void getRootChains(Certificate[] certificates, List chains)
+    private void getRootChains(Certificate[] certificates, List chains,
+        boolean check)
     {
         List chain = new ArrayList();
 
@@ -394,11 +423,14 @@
             {
                 revoked = true;
             }
-            else if (!revoked)
+            if (!check || !revoked)
             {
                 try
                 {
-                    certificate.checkValidity();
+                    if (check)
+                    {
+                        certificate.checkValidity();
+                    }
 
                     chain.add(certificate);
                 }
@@ -412,7 +444,7 @@
             if (!((X509Certificate) certificates[i + 1]).getSubjectDN().equals(
                 certificate.getIssuerDN()))
             {
-                if (!revoked && trusted(certificate))
+                if (!check || (!revoked && trusted(certificate)))
                 {
                     chains.add(chain);
                 }
@@ -427,10 +459,11 @@
         }
         // The final entry in the certs array is always
         // a "root" certificate
-        if (!revoked)
+        if (!check || !revoked)
         {
             chain.add(certificates[certificates.length - 1]);
-            if (trusted((X509Certificate) certificates[certificates.length - 1]))
+            if (!check
+                || trusted((X509Certificate) certificates[certificates.length - 1]))
             {
                 chains.add(chain);
             }
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SignerMatcher.java b/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SignerMatcher.java
deleted file mode 100644
index 98509d6..0000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SignerMatcher.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * 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.security.verifier;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.moduleloader.IModule;
-
-public final class SignerMatcher
-{
-    private final String m_filter;
-    private final String m_root;
-    private final IContent m_archive;
-    private final BundleDNParser m_parser;
-    private final long m_lastModified;
-    
-    public SignerMatcher(String filter)
-    {
-        m_filter = filter;
-        m_root = null;
-        m_archive = null;
-        m_parser = null;
-        m_lastModified = 0;
-    }
-    
-    public SignerMatcher(String root, long lastModified, IContent archive, BundleDNParser parser)
-    {
-        m_filter = null;
-        m_root = root;
-        m_archive = archive;
-        m_parser = parser;
-        m_lastModified = lastModified;
-    }
-
-    public boolean equals(Object o)
-    {
-        if (!(o instanceof SignerMatcher))
-        {
-            return false;
-        }
-
-        String pattern = ((SignerMatcher) o).m_filter;
-
-        if (pattern == null)
-        {
-            return true;
-        }
-
-        if (m_archive == null)
-        {
-            return pattern.trim().equals("\\*");
-        }
-
-        String[] dns;
-        try
-        {
-            dns = m_parser.getDNChains(m_root + "-" + m_lastModified, m_archive);
-        }
-        catch (Exception ex)
-        {
-            // TODO: log this or something
-            ex.printStackTrace();
-            return false;
-        }
-
-        if (dns == null)
-        {
-            return pattern.trim().equals("\\*");
-        }
-
-        for (int i = 0;i < dns.length;i++)
-        {
-            if (match(pattern, dns[i]))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-    
-    public int hashCode()
-    {
-        return 42; 
-    }
-    
-    // see core spec 2.3
-    public static boolean match(String pattern, String dn)
-    {
-        try
-        {
-            return ((pattern != null) && (dn != null)) ?
-                matchDN(pattern.toCharArray(), 0, dn.toCharArray(), 0) : false;
-        }
-        catch (Exception ex)
-        {
-            // TODO: log this or something
-            ex.printStackTrace();
-        }
-
-        return false;
-    }
-
-    private static boolean matchDN(char[] pattern, int pPos, char[] dn, int dPos)
-    {
-        pPos = skip(pattern, pPos, ' ');
-
-        if (pPos >= pattern.length)
-        {
-            return true;
-        }
-
-        int befor = pPos;
-
-        if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
-        {
-            pPos = pPos + 1;
-        }
-
-        switch (pattern[pPos++])
-        {
-            case '*':
-                pPos = skip(pattern, pPos, ' ');
-                if ((pPos < pattern.length) && (pattern[pPos] == ';'))
-                {
-                    if (matchDN(pattern, ++pPos, dn, dPos))
-                    {
-                        return true;
-                    }
-                    return matchDN(pattern, pPos, dn, skipEscapedUntil(dn, dPos, ';') + 1);
-                }
-                if (pPos >= pattern.length)
-                {
-                    return true;
-                }
-                return matchRDN(pattern, befor, dn, dPos);
-            case '-':
-                pPos = skip(pattern, pPos, ' ');
-                if ((pPos < pattern.length) && (pattern[pPos] == ';'))
-                {
-                    int next = dPos;
-                    pPos++;
-                    do
-                    {
-                        if (matchDN(pattern, pPos, dn, next))
-                        {
-                            return true;
-                        }
-                        next = skipEscapedUntil(dn, next, ';') + 1;
-                    } while (next < dn.length);
-
-                    return false;
-                }
-                if (pPos >= pattern.length)
-                {
-                    return true;
-                }
-                throw new IllegalArgumentException("[" + pPos + "]" + new String(pattern));
-            default:
-                break;
-        }
-
-        return matchRDN(pattern, befor, dn, dPos);
-    }
-
-    private static boolean matchRDN(char[] pattern, int pPos, char[] dn, int dPos)
-    {
-        pPos = skip(pattern, pPos, ' ');
-
-        if (pPos >= pattern.length)
-        {
-            return true;
-        }
-
-        if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
-        {
-            pPos = pPos + 1;
-        }
-
-        switch (pattern[pPos++])
-        {
-            case '*':
-                pPos = skip(pattern, pPos, ' ');
-                if ((pPos < pattern.length) && (pattern[pPos] == ','))
-                {
-                    pPos++;
-                    do
-                    {
-                        if (matchKV(pattern, pPos, dn, dPos))
-                        {
-                            return true;
-                        }
-
-                        int comma = skipEscapedUntil(dn, dPos, ',');
-                        int colon = skipEscapedUntil(dn, dPos, ';');
-
-                        dPos = (comma > colon) ? colon : comma;
-                    } while ((dPos < dn.length) && (dn[dPos++] == ','));
-                    return false;
-                }
-                throw new IllegalArgumentException("[" + pPos + "]" + new String(pattern));
-            default:
-                break;
-        }
-
-        return matchKV(pattern, pPos - 1, dn, dPos);
-    }
-
-    private static boolean matchKV(char[] pattern, int pPos, char[] dn, int dPos)
-    {
-        pPos = skip(pattern, pPos, ' ');
-
-        if (pPos >= pattern.length)
-        {
-            return false;
-        }
-
-        int equals = skipEscapedUntil(pattern, pPos, '=');
-        int comma = skipEscapedUntil(pattern, pPos, ',');
-        int colon = skipEscapedUntil(pattern, pPos, ';');
-        if (((colon < pattern.length) && (colon < equals)) ||
-            ((comma < pattern.length) && (comma < equals)) ||
-            (equals >= pattern.length))
-        {
-            return false;
-        }
-
-        String key = (String) KEY2OIDSTRING.get(
-            new String(pattern, pPos, equals - pPos).toLowerCase(Locale.US).trim());
-
-        if (key == null)
-        {
-            throw new IllegalArgumentException("Bad key [" +
-                new String(pattern, pPos, equals - pPos) + "] in [" +
-                new String(pattern) + "]");
-        }
-
-        pPos = equals + 1;
-        int keylength = key.length();
-        for (int i = 0;i < keylength;i++)
-        {
-            if ((dPos >= dn.length) || (key.charAt(i) != dn[dPos++]))
-            {
-                return false;
-            }
-        }
-
-        if ((dPos >= dn.length) || (dn[dPos++] != '='))
-        {
-            return false;
-        }
-
-        pPos = skip(pattern, pPos, ' ');
-        if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
-        {
-            pPos = skip(pattern, pPos + 2, ' ');
-            if (pPos >= pattern.length)
-            {
-                return true;
-            }
-            comma = skipEscapedUntil(dn, dPos, ',');
-            colon = skipEscapedUntil(dn, dPos, ';');
-            if ((pattern[pPos] == ',') && (colon > comma))
-            {
-                return matchKV(pattern, ++pPos, dn, comma + 1);
-            }
-
-            if (pattern[pPos] == ';' )
-            {
-                return matchDN(pattern, ++pPos, dn, colon + 1);
-            }
-
-            return false;
-        }
-        boolean escaped = false;
-        while ((pPos < pattern.length) && (dPos < dn.length))
-        {
-            switch (Character.toLowerCase(pattern[pPos++]))
-            {
-                case ' ':
-                    if ((pattern[pPos - 2] != ' ') && ((dn[dPos++] != ' ') &&
-                        (dn[--dPos] != ';') && (dn[dPos] != ',')))
-                    {
-                        return false;
-                    }
-                    break;
-                case '\\':
-                    escaped = !escaped;
-                    break;
-
-                case '(':
-                case ')':
-                    if (escaped)
-                    {
-                        if (dn[dPos++] != pattern[pPos - 1])
-                        {
-                            return false;
-                        }
-                        escaped = false;
-                        break;
-                    }
-                    return false;
-                case ';':
-                    if (!escaped)
-                    {
-                        if ((dPos < dn.length) && ((dn[dPos] == ',') || (dn[dPos] == ';')))
-                        {
-                            return matchDN(pattern, pPos, dn, skipEscapedUntil(dn, dPos, ';') + 1);
-                        }
-                        return false;
-                    }
-                case ',':
-                    if (!escaped)
-                    {
-                        if ((dPos < dn.length) && (dn[dPos] == ','))
-                        {
-                            return matchKV(pattern, pPos, dn, dPos + 1);
-                        }
-                        return false;
-                    }
-                default:
-                    if (escaped)
-                    {
-                        if (dn[dPos++] != '\\')
-                        {
-                            return false;
-                        }
-                        escaped = false;
-                    }
-                    if (dn[dPos++] != Character.toLowerCase(pattern[pPos - 1]))
-                    {
-                        return false;
-                    }
-                    break;
-            }
-        }
-
-        pPos = skip(pattern, pPos, ' ');
-        if (pPos >= pattern.length)
-        {
-            if ((dPos >= dn.length) || (dn[dPos] == ',') || (dn[dPos] == ';'))
-            {
-                return true;
-            }
-        }
-        else
-        {
-            switch (pattern[pPos++])
-            {
-                case ',':
-                    return matchKV(pattern, pPos, dn, dPos);
-                case ';':
-                    return matchDN(pattern, pPos, dn, dPos);
-                default:
-                    break;
-            }
-        }
-
-        return false;
-    }
-
-    private static final Map KEY2OIDSTRING = new HashMap();
-
-    static {
-        KEY2OIDSTRING.put("2.5.4.3", "cn");
-        KEY2OIDSTRING.put("cn", "cn");
-        KEY2OIDSTRING.put("commonname", "cn");
-        KEY2OIDSTRING.put("2.5.4.4", "sn");
-        KEY2OIDSTRING.put("sn", "sn");
-        KEY2OIDSTRING.put("surname", "sn");
-        KEY2OIDSTRING.put("2.5.4.6", "c");
-        KEY2OIDSTRING.put("c", "c");
-        KEY2OIDSTRING.put("countryname", "c");
-        KEY2OIDSTRING.put("2.5.4.7", "l");
-        KEY2OIDSTRING.put("l", "l");
-        KEY2OIDSTRING.put("localityname", "l");
-        KEY2OIDSTRING.put("2.5.4.8", "st");
-        KEY2OIDSTRING.put("st", "st");
-        KEY2OIDSTRING.put("stateorprovincename", "st");
-        KEY2OIDSTRING.put("2.5.4.10", "o");
-        KEY2OIDSTRING.put("o", "o");
-        KEY2OIDSTRING.put("organizationname", "o");
-        KEY2OIDSTRING.put("2.5.4.11", "ou");
-        KEY2OIDSTRING.put("ou", "ou");
-        KEY2OIDSTRING.put("organizationalunitname", "ou");
-        KEY2OIDSTRING.put("2.5.4.12", "title");
-        KEY2OIDSTRING.put("t", "title");
-        KEY2OIDSTRING.put("title", "title");
-        KEY2OIDSTRING.put("2.5.4.42", "givenname");
-        KEY2OIDSTRING.put("givenname", "givenname");
-        KEY2OIDSTRING.put("2.5.4.43", "initials");
-        KEY2OIDSTRING.put("initials", "initials");
-        KEY2OIDSTRING.put("2.5.4.44", "generationqualifier");
-        KEY2OIDSTRING.put("generationqualifier", "generationqualifier");
-        KEY2OIDSTRING.put("2.5.4.46", "dnqualifier");
-        KEY2OIDSTRING.put("dnqualifier", "dnqualifier");
-        KEY2OIDSTRING.put("2.5.4.9", "street");
-        KEY2OIDSTRING.put("street", "street");
-        KEY2OIDSTRING.put("streetaddress", "street");
-        KEY2OIDSTRING.put("0.9.2342.19200300.100.1.25", "dc");
-        KEY2OIDSTRING.put("dc", "dc");
-        KEY2OIDSTRING.put("domaincomponent", "dc");
-        KEY2OIDSTRING.put("0.9.2342.19200300.100.1.1", "uid");
-        KEY2OIDSTRING.put("uid", "uid");
-        KEY2OIDSTRING.put("userid", "uid");
-        KEY2OIDSTRING.put("1.2.840.113549.1.9.1", "emailaddress");
-        KEY2OIDSTRING.put("emailaddress", "emailaddress");
-        KEY2OIDSTRING.put("2.5.4.5", "serialnumber");
-        KEY2OIDSTRING.put("serialnumber", "serialnumber");
-    }
-
-    private static int skipEscapedUntil(char[] string, int pos, char value)
-    {
-        boolean escaped = false;
-
-        while (pos < string.length)
-        {
-            switch (string[pos++])
-            {
-                case '\\':
-                    escaped = true;
-                    break;
-                default:
-                    if (!escaped)
-                    {
-                        if (string[pos - 1] == value)
-                        {
-                            return pos - 1;
-                        }
-                    }
-                    escaped = false;
-                    break;
-            }
-        }
-
-        return pos;
-    }
-
-    private static int skip(char[] string, int pos, char value)
-    {
-        while (pos < string.length)
-        {
-            if (string[pos] != value)
-            {
-                break;
-            }
-            pos++;
-        }
-
-        return pos;
-    }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SubjectDNParser.java b/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SubjectDNParser.java
deleted file mode 100644
index 1c34021..0000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SubjectDNParser.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * 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.security.verifier;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-public final class SubjectDNParser
-{
-    private static final Map OID2NAME = new HashMap();
-
-    static
-    {
-        // see core-spec 2.3.5
-        OID2NAME.put("2.5.4.3", "cn");
-        OID2NAME.put("2.5.4.4", "sn");
-        OID2NAME.put("2.5.4.6", "c");
-        OID2NAME.put("2.5.4.7", "l");
-        OID2NAME.put("2.5.4.8", "st");
-        OID2NAME.put("2.5.4.10", "o");
-        OID2NAME.put("2.5.4.11", "ou");
-        OID2NAME.put("2.5.4.12", "title");
-        OID2NAME.put("2.5.4.42", "givenname");
-        OID2NAME.put("2.5.4.43", "initials");
-        OID2NAME.put("2.5.4.44", "generationqualifier");
-        OID2NAME.put("2.5.4.46", "dnqualifier");
-        OID2NAME.put("2.5.4.9", "street");
-        OID2NAME.put("0.9.2342.19200300.100.1.25", "dc");
-        OID2NAME.put("0.9.2342.19200300.100.1.1", "uid");
-        OID2NAME.put("1.2.840.113549.1.9.1", "emailaddress");
-        OID2NAME.put("2.5.4.5", "serialnumber");
-        // p.s.: it sucks that the spec doesn't list some of the oids used
-        // p.p.s: it sucks that the spec doesn't list the short form for all names
-        // In summary, there is a certain amount of guess-work involved but I'm
-        // fairly certain I've got it right.
-    }
-    
-    private byte[] m_buffer;
-    private int m_offset  = 0;
-    private int m_tagOffset = 0;
-    private int m_tag = -1;
-    private int m_length = -1;
-    private int m_contentOffset = -1;
-    
-    /*
-     * This is deep magiK, bare with me. The problem is that we don't get
-     * access to the original subject dn in a certificate without resorting to
-     * sun.* classes or running on something > OSGi-minimum/jdk1.3. Furthermore,
-     * we need access to it because there is no other way to escape it properly.
-     * Note, this is due to missing of a public X500Name in OSGI-minimum/jdk1.3
-     * a.k.a foundation.
-     *
-     * The solution is to get the DER encoded TBS certificate bytes via the
-     * available java methods and parse-out the subject dn in canonical form by
-     * hand. This is possible without deploying a full-blown BER encoder/decoder
-     * due to java already having done all the cumbersome verification and
-     * normalization work.
-     *
-     * The following skips through the TBS certificate bytes until it reaches and
-     * subsequently parses the subject dn. If the below makes immediate sense to
-     * you - you either are a X509/X501/DER expert or quite possibly mad. In any
-     * case, please seek medical care immediately.
-     */
-    public String parseSubjectDN(byte[] tbsBuffer) throws Exception
-    {
-        // init
-        m_buffer = tbsBuffer;
-        m_offset = 0;
-
-        // TBSCertificate  ::=  SEQUENCE  {
-        //    version         [0]  EXPLICIT Version DEFAULT v1,
-        //    serialNumber         CertificateSerialNumber,
-        //    signature            AlgorithmIdentifier,
-        //    issuer               Name,
-        //    validity             Validity,
-        //    subject              Name,
-        //
-        // WE CAN STOP!
-        //
-        //    subjectPublicKeyInfo SubjectPublicKeyInfo,
-        //    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
-        //                         -- If present, version must be v2 or v3
-        //    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
-        //                         -- If present, version must be v2 or v3
-        //    extensions      [3]  EXPLICIT Extensions OPTIONAL
-        //                         -- If present, version must be v3
-        //    }
-        try 
-        {
-            next();
-            next();
-            // if a version is present skip it
-            if (m_tag == 0)
-            {
-                next();
-                m_offset += m_length;
-            }
-            m_offset += m_length;
-            // skip the serialNumber
-            next();
-            next();
-            m_offset += m_length;
-            // skip the signature
-            next();
-            m_offset += m_length;
-            // skip the issuer
-            // The issuer is a sequence of sets of issuer dns like the subject later on -
-            // we just skip it.
-            next();
-            int endOffset = m_offset + m_length;
-    
-            int seqTagOffset = m_tagOffset;
-    
-            // skip the sequence
-            while (endOffset > m_offset)
-            {
-                next();
-    
-                int endOffset2 = m_offset + m_length;
-    
-                int seqTagOffset2 = m_tagOffset;
-    
-                // skip each set
-                while (endOffset2 > m_offset)
-                {
-                    next();
-                    next();
-                    m_offset += m_length;
-                    next();
-                    m_offset += m_length;
-                }
-    
-                m_tagOffset = seqTagOffset2;
-            }
-    
-            m_tagOffset = seqTagOffset;
-            // skip the validity which contains two dates to be skiped
-            next();
-            next();
-            m_offset += m_length;
-            next();
-            m_offset += m_length;
-            next();
-            // Now extract the subject dns and add them to attributes
-            List attributes = new ArrayList();
-    
-            endOffset = m_offset + m_length;
-    
-            seqTagOffset = m_tagOffset;
-    
-            // for each set of rdns
-            while (endOffset > m_offset)
-            {
-                next();
-                int endOffset2 = m_offset + m_length;
-    
-                // store tag offset
-                int seqTagOffset2 = m_tagOffset;
-    
-                List rdn = new ArrayList();
-    
-                // for each rdn in the set
-                while (endOffset2 > m_offset)
-                {
-                    next();
-                    next();
-                    m_offset += m_length;
-                    // parse the oid of the rdn
-                    int oidElement = 1;
-                    for (int i = 0; i < m_length; i++, ++oidElement)
-                    {
-                        while ((m_buffer[m_contentOffset + i] & 0x80) == 0x80)
-                        {
-                            i++;
-                        }
-                    }
-                    int[] oid = new int[oidElement];
-                    for (int id = 1, i = 0; id < oid.length; id++, i++)
-                    {
-                        int octet = m_buffer[m_contentOffset + i];
-                        oidElement = octet & 0x7F;
-                        while ((octet & 0x80) != 0)
-                        {
-                            i++;
-                            octet = m_buffer[m_contentOffset + i];
-                            oidElement = oidElement << 7 | (octet & 0x7f);
-                        }
-                        oid[id] = oidElement;
-                    }
-                    // The first OID is special
-                    if (oid[1] > 79)
-                    {
-                        oid[0] = 2;
-                        oid[1] = oid[1] - 80;
-                    }
-                    else
-                    {
-                        oid[0] = oid[1] / 40;
-                        oid[1] = oid[1] % 40;
-                    }
-                    // Now parse the value of the rdn
-                    next();
-                    String str = null;
-                    int tagTmp = m_tag;
-                    m_offset += m_length;
-                    switch(tagTmp)
-                    {
-                        case 30: // BMPSTRING
-                        case 22: // IA5STRING
-                        case 27: // GENERALSTRING
-                        case 19: // PRINTABLESTRING
-                        case 20: // TELETEXSTRING && T61STRING
-                        case 28: // UNIVERSALSTRING
-                            str = new String(m_buffer, m_contentOffset,
-                                m_length);
-                            break;
-                        case 12: // UTF8_STRING
-                            str = new String(m_buffer, m_contentOffset,
-                                m_length, "UTF-8");
-                            break;
-                        default: // OCTET
-                            byte[] encoded = new byte[m_offset - m_tagOffset];
-                            System.arraycopy(m_buffer, m_tagOffset, encoded,
-                                0, encoded.length);
-                            // Note, I'm not sure this is allowed by the spec
-                            // i.e., whether OCTET subjects are allowed at all
-                            // but it shouldn't harm doing it anyways (we just
-                            // convert it into a hex string prefixed with \#).
-                            str = toHexString(encoded);
-                            break;
-                    }
-    
-                    rdn.add(new Object[]{mapOID(oid), makeCanonical(str)});
-                }
-    
-                attributes.add(rdn);
-                m_tagOffset = seqTagOffset2;
-            }
-    
-            m_tagOffset = seqTagOffset;
-    
-            StringBuffer result = new StringBuffer();
-    
-            for (int i = attributes.size() - 1; i >= 0; i--)
-            {
-                List rdn = (List) attributes.get(i);
-                Collections.sort(rdn, new Comparator()
-                {
-                    public int compare(Object obj1, Object obj2)
-                    {
-                        return ((String) ((Object[]) obj1)[0]).compareTo(
-                            ((String) ((Object[])obj2)[0]));
-                    }
-                });
-    
-                for (Iterator iter = rdn.iterator();iter.hasNext();)
-                {
-                    Object[] att = (Object[]) iter.next();
-                    result.append((String) att[0]);
-                    result.append('=');
-                    result.append((String) att[1]);
-    
-                    if (iter.hasNext())
-                    {
-                        // multi-valued RDN
-                        result.append('+');
-                    }
-                }
-    
-                if (i != 0)
-                {
-                    result.append(',');
-                }
-            }
-            
-
-            // the spec says:
-            // return result.toString().toUpperCase(Locale.US).toLowerCase(Locale.US);
-            // which is needed because toLowerCase can be ambiguous in unicode when
-            // used on mixed case while toUpperCase not hence, this way its ok.
-            return result.toString().toUpperCase(Locale.US).toLowerCase(Locale.US);
-        }
-        finally
-        {
-            m_buffer = null;
-        }
-    }
-
-    // Determine the type of the current sequence (tbs_tab), and the length and
-    // offset of it (tbs_length and tbs_tagOffset) plus increment the global
-    // offset (tbs_offset) accordingly. Note, we don't need to check for
-    // the indefinite length because this is supposed to be DER not BER (and
-    // we implicitly assume that java only gives us valid DER).
-    private void next()
-    {
-        m_tagOffset = m_offset;
-        m_tag = m_buffer[m_offset++] & 0xFF;
-        m_length = m_buffer[m_offset++] & 0xFF;
-        // There are two kinds of length forms - make sure we use the right one
-        if ((m_length & 0x80) != 0)
-        {
-            // its the long kind
-            int numOctets = m_length & 0x7F;
-            // hence, convert it
-            m_length = m_buffer[m_offset++] & 0xFF;
-            for (int i = 1; i < numOctets; i++)
-            {
-                int ch = m_buffer[m_offset++] & 0xFF;
-                m_length = (m_length << 8) + ch;
-            }
-        }
-        m_contentOffset = m_offset;
-    }
-
-    private String makeCanonical(String value)
-    {
-        int len = value.length();
-
-        if (len == 0)
-        {
-            return value;
-        }
-
-        StringBuffer result = new StringBuffer(len);
-
-        int i = 0;
-        if (value.charAt(0) == '#')
-        {
-            result.append('\\');
-            result.append('#');
-            i++;
-        }
-        for (;i < len; i++)
-        {
-            char c = value.charAt(i);
-
-            switch (c)
-            {
-                case ' ':
-                    int pos = result.length();
-                    // remove leading spaces and
-                    // remove all spaces except one in any sequence of spaces
-                    if ((pos == 0) || (result.charAt(pos - 1) == ' '))
-                    {
-                        break;
-                    }
-                    result.append(' ');
-                    break;
-                case '"':
-                case '\\':
-                case ',':
-                case '+':
-                case '<':
-                case '>':
-                case ';':
-                    result.append('\\');
-                default:
-                    result.append(c);
-            }
-        }
-
-        // count down until first none space to remove trailing spaces
-        i = result.length() - 1;
-        while ((i > -1) && (result.charAt(i) == ' '))
-        {
-            i--;
-        }
-
-        result.setLength(i + 1);
-
-        return result.toString();
-    }
-
-    private String toHexString(byte[] encoded)
-    {
-        StringBuffer result = new StringBuffer();
-
-        result.append('#');
-
-        for (int i = 0; i < encoded.length; i++)
-        {
-            int c = (encoded[i] >> 4) & 0x0F;
-            if (c < 10)
-            {
-                result.append((char) (c + 48));
-            }
-            else
-            {
-                result.append((char) (c + 87));
-            }
-
-            c = encoded[i] & 0x0F;
-
-            if (c < 10)
-            {
-                result.append((char) (c + 48));
-            }
-            else
-            {
-                result.append((char) (c + 87));
-            }
-        }
-
-        return result.toString();
-    }
-
-    // This just creates a string of the oid and looks for its name in the
-    // known names map OID2NAME. There might be faster implementations :-)
-    private String mapOID(int[] oid)
-    {
-        StringBuffer oidString = new StringBuffer();
-
-        oidString.append(oid[0]);
-        for (int i = 1;i < oid.length;i++)
-        {
-            oidString.append('.');
-            oidString.append(oid[i]);
-        }
-
-        String result = (String) OID2NAME.get(oidString.toString());
-
-        if (result == null)
-        {
-            throw new IllegalArgumentException("Unknown oid: " + oidString.toString());
-        }
-
-        return result;
-    }
-}
\ No newline at end of file
diff --git a/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java b/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java
deleted file mode 100644
index 3f66514..0000000
--- a/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleLocationCondition.java,v 1.18 2006/06/16 16:31:37 hargrave Exp $
- * 
- * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
- * 
- * Licensed 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.osgi.service.condpermadmin;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Hashtable;
-
-import org.osgi.framework.*;
-
-/**
- * Condition to test if the location of a bundle matches a pattern. Pattern
- * matching is done according to the filter string matching rules.
- * 
- * @version $Revision: 1.18 $
- */
-public class BundleLocationCondition
-{
-    private static final String CONDITION_TYPE =
-        "org.osgi.service.condpermadmin.BundleLocationCondition";
-
-    /**
-     * Constructs a condition that tries to match the passed Bundle's location
-     * to the location pattern.
-     * 
-     * @param bundle
-     *                The Bundle being evaluated.
-     * @param info
-     *                The ConditionInfo to construct the condition for. The args
-     *                of the ConditionInfo must be a single String which
-     *                specifies the location pattern to match against the Bundle
-     *                location. Matching is done according to the filter string
-     *                matching rules. Any '*' characters in the location
-     *                argument are used as wildcards when matching bundle
-     *                locations unless they are escaped with a '\' character.
-     * @return Condition object for the requested condition.
-     */
-    static public Condition getCondition(final Bundle bundle, ConditionInfo info)
-    {
-        if (!CONDITION_TYPE.equals(info.getType()))
-            throw new IllegalArgumentException(
-                "ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
-        String[] args = info.getArgs();
-        if (args.length != 1)
-            throw new IllegalArgumentException("Illegal number of args: "
-                + args.length);
-        String bundleLocation =
-            (String) AccessController.doPrivileged(new PrivilegedAction()
-            {
-                public Object run()
-                {
-                    return bundle.getLocation();
-                }
-            });
-        Filter filter = null;
-        try
-        {
-            filter =
-                FrameworkUtil.createFilter("(location=" + escapeLocation(args[0]) + ")");
-        }
-        catch (InvalidSyntaxException e)
-        {
-            // this should never happen, but just incase
-            throw new RuntimeException("Invalid filter: " + e.getFilter());
-        }
-        Hashtable matchProps = new Hashtable(2);
-        matchProps.put("location", bundleLocation);
-        return filter.match(matchProps) ? Condition.TRUE : Condition.FALSE;
-    }
-
-    private BundleLocationCondition()
-    {
-        // private constructor to prevent objects of this type
-    }
-
-    /**
-     * Escape the value string such that '(', ')' and '\' are escaped. The '\'
-     * char is only escaped if it is not followed by a '*'.
-     * 
-     * @param value
-     *                unescaped value string.
-     * @return escaped value string.
-     */
-    private static String escapeLocation(String value)
-    {
-        boolean escaped = false;
-        int inlen = value.length();
-        int outlen = inlen << 1; /* inlen * 2 */
-
-        char[] output = new char[outlen];
-        value.getChars(0, inlen, output, inlen);
-
-        int cursor = 0;
-        for (int i = inlen; i < outlen; i++)
-        {
-            char c = output[i];
-            switch (c)
-            {
-                case '\\':
-                    if (i + 1 < outlen && output[i + 1] == '*')
-                        break;
-                case '(':
-                case ')':
-                    output[cursor] = '\\';
-                    cursor++;
-                    escaped = true;
-                    break;
-            }
-
-            output[cursor] = c;
-            cursor++;
-        }
-
-        return escaped ? new String(output, 0, cursor) : value;
-    }
-}
diff --git a/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java b/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java
deleted file mode 100644
index 91f2854..0000000
--- a/framework.security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleSignerCondition.java,v 1.10 2006/06/16 16:31:37 hargrave Exp $
- * 
- * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
- * 
- * Licensed 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.osgi.service.condpermadmin;
-
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-
-/**
- * Condition to test if the signer of a bundle matches a pattern. Since the
- * bundle's signer can only change when the bundle is updated, this condition is
- * immutable.
- * <p>
- * The condition expressed using a single String that specifies a Distinguished
- * Name (DN) chain to match bundle signers against. DN's are encoded using IETF
- * RFC 2253. Usually signers use certificates that are issued by certificate
- * authorities, which also have a corresponding DN and certificate. The
- * certificate authorities can form a chain of trust where the last DN and
- * certificate is known by the framework. The signer of a bundle is expressed as
- * signers DN followed by the DN of its issuer followed by the DN of the next
- * issuer until the DN of the root certificate authority. Each DN is separated
- * by a semicolon.
- * <p>
- * A bundle can satisfy this condition if one of its signers has a DN chain that
- * matches the DN chain used to construct this condition. Wildcards (`*') can be
- * used to allow greater flexibility in specifying the DN chains. Wildcards can
- * be used in place of DNs, RDNs, or the value in an RDN. If a wildcard is used
- * for a value of an RDN, the value must be exactly "*" and will match any value
- * for the corresponding type in that RDN. If a wildcard is used for a RDN, it
- * must be the first RDN and will match any number of RDNs (including zero
- * RDNs).
- * 
- * @version $Revision: 1.10 $
- */
-/*
- * TODO: In our case the above is not correct. We don't make this an immutable
- * condition because the spec is somewhat ambiguous in regard to when the
- * signature change. This probably has to be clarified and then revisited later.
- */
-public class BundleSignerCondition
-{
-    /*
-     * NOTE: A framework implementor may also choose to replace this class in
-     * their distribution with a class that directly interfaces with the
-     * framework implementation. This replacement class MUST NOT alter the
-     * public/protected signature of this class.
-     */
-
-    private static final String CONDITION_TYPE =
-        "org.osgi.service.condpermadmin.BundleSignerCondition";
-
-    /**
-     * Constructs a Condition that tries to match the passed Bundle's location
-     * to the location pattern.
-     * 
-     * @param bundle
-     *                The Bundle being evaluated.
-     * @param info
-     *                The ConditionInfo to construct the condition for. The args
-     *                of the ConditionInfo specify a single String specifying
-     *                the chain of distinguished names pattern to match against
-     *                the signer of the Bundle.
-     * @return A Condition which checks the signers of the specified bundle.
-     */
-    static public Condition getCondition(Bundle bundle, ConditionInfo info)
-    {
-        if (!CONDITION_TYPE.equals(info.getType()))
-            throw new IllegalArgumentException(
-                "ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
-        final String[] args = info.getArgs();
-        if (args.length != 1)
-            throw new IllegalArgumentException("Illegal number of args: "
-                + args.length);
-
-        return new ConditionImpl(bundle, "(signer=" + escapeFilter(args[0])
-            + ")");
-
-    }
-
-    private static String escapeFilter(String string)
-    {
-        boolean escaped = false;
-        int inlen = string.length();
-        int outlen = inlen << 1; /* inlen * 2 */
-
-        char[] output = new char[outlen];
-        string.getChars(0, inlen, output, inlen);
-
-        int cursor = 0;
-        for (int i = inlen; i < outlen; i++)
-        {
-            char c = output[i];
-            switch (c)
-            {
-                case '\\':
-                case '(':
-                case ')':
-                case '*':
-                    output[cursor] = '\\';
-                    cursor++;
-                    escaped = true;
-                    break;
-            }
-
-            output[cursor] = c;
-            cursor++;
-        }
-
-        return escaped ? new String(output, 0, cursor) : string;
-    }
-
-    private BundleSignerCondition()
-    {
-        // private constructor to prevent objects of this type
-    }
-}
-
-final class ConditionImpl implements Condition, PrivilegedExceptionAction
-{
-    private static final Method m_getSignerMatcher;
-
-    static
-    {
-        m_getSignerMatcher =
-            (Method) AccessController.doPrivileged(new PrivilegedAction()
-            {
-                public Object run()
-                {
-                    Method getSignerMatcher = null;
-                    try
-                    {
-                        getSignerMatcher =
-                            Class.forName(
-                                "org.apache.felix.framework.BundleImpl")
-                                .getDeclaredMethod("getSignerMatcher", null);
-                        getSignerMatcher.setAccessible(true);
-                    }
-                    catch (Exception ex)
-                    {
-                        ex.printStackTrace();
-                        getSignerMatcher = null;
-                    }
-                    return getSignerMatcher;
-                }
-            });
-    }
-
-    private final Bundle m_bundle;
-    private final Filter m_filter;
-    private final Dictionary m_dict;
-
-    ConditionImpl(Bundle bundle, String filter)
-    {
-        m_bundle = bundle;
-        try
-        {
-            m_filter = FrameworkUtil.createFilter(filter);
-        }
-        catch (InvalidSyntaxException e)
-        {
-            throw new IllegalArgumentException(e.getMessage());
-        }
-        try
-        {
-            Object signerMatcher = AccessController.doPrivileged(this);
-            m_dict = new Hashtable();
-            m_dict.put("signer", signerMatcher);
-        }
-        catch (PrivilegedActionException e)
-        {
-            if (e.getException() instanceof RuntimeException)
-            {
-                throw (RuntimeException) e.getException();
-            }
-
-            throw new RuntimeException(e.getException().getMessage());
-        }
-    }
-
-    public boolean isMutable()
-    {
-        return true;
-    }
-
-    public boolean isPostponed()
-    {
-        return false;
-    }
-
-    public Object run() throws Exception
-    {
-        return m_getSignerMatcher.invoke(m_bundle, null);
-    }
-
-    public boolean isSatisfied()
-    {
-        return m_filter.match(m_dict);
-    }
-
-    public boolean isSatisfied(Condition[] conditions, Dictionary context)
-    {
-        return false;
-    }
-}
\ No newline at end of file