Add the ability to specify keystores with trustedCaCerts to main and 
subsequently, pass it to the framework in order to enable digitally 
signed bundles (FELIX-22).


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@434387 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/main/src/main/java/org/apache/felix/main/Main.java b/main/src/main/java/org/apache/felix/main/Main.java
index cb03a8f..4aeee72 100644
--- a/main/src/main/java/org/apache/felix/main/Main.java
+++ b/main/src/main/java/org/apache/felix/main/Main.java
@@ -19,6 +19,7 @@
 import java.io.*;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.security.*;
 import java.util.*;
 
 import org.apache.felix.framework.Felix;
@@ -58,6 +59,21 @@
     **/
     public static final String CONFIG_PROPERTIES_FILE_VALUE = "config.properties";
 
+    public static final String KEYSTORE_FILE_PROP = "felix.keystore";
+
+    public static final String KEYSTORE_FILE_VALUE = System.getProperty("java.home") +
+        File.separatorChar + "lib" + File.separatorChar + "security" +
+        File.separatorChar + "cacerts" + File.pathSeparatorChar + System.getProperty("user.home") +
+        File.separatorChar + ".keystore";
+
+    public static final String KEYSTORE_TYPE_PROP = "felix.keystore.type";
+
+    public static final String KEYSTORE_TYPE_VALUE = "JKS" + File.pathSeparatorChar + "JKS";
+
+    public static final String KEYSTORE_PASS_PROP = "felix.keystore.pass";
+
+    public static final String KEYSTORE_PASS_VALUE = "changeit" + File.pathSeparatorChar + "changeit";
+
     private static Felix m_felix = null;
 
     /**
@@ -189,7 +205,7 @@
             m_felix = new Felix();
             m_felix.start(
                 new MutablePropertyResolverImpl(new StringMap(configProps, false)),
-                null);
+                null, (System.getSecurityManager() == null) ? null : new TrustManager(configProps));
         }
         catch (Exception ex)
         {
@@ -451,10 +467,10 @@
         {
             cycleMap = new HashMap();
         }
-    
+
         // Put the current key in the cycle map.
         cycleMap.put(currentKey, currentKey);
-    
+
         // Assume we have a value that is something like:
         // "leading ${foo.${bar}} middle ${baz} trailing"
 
@@ -540,4 +556,119 @@
         // Return the value.
         return val;
     }
+
+    private static class TrustManager extends AbstractCollection
+    {
+        private String[] m_keystores = null;
+        private String[] m_passwds = null;
+        private String[] m_types = null;
+        private ArrayList m_stores = null;
+
+        TrustManager(Properties config)
+        {
+            StringTokenizer tok = new StringTokenizer(System.getProperty(KEYSTORE_FILE_PROP,
+                config.getProperty(KEYSTORE_FILE_PROP, KEYSTORE_FILE_VALUE)), File.pathSeparator);
+
+            m_keystores = new String[tok.countTokens()];
+
+            for (int i = 0;tok.hasMoreTokens();i++)
+            {
+                m_keystores[i] = tok.nextToken();
+            }
+
+            tok = new StringTokenizer(System.getProperty(KEYSTORE_PASS_PROP,
+                config.getProperty(KEYSTORE_PASS_PROP, KEYSTORE_PASS_VALUE)), File.pathSeparator);
+
+            m_passwds = new String[tok.countTokens()];
+
+            for (int i = 0;tok.hasMoreTokens();i++)
+            {
+                m_passwds[i] = tok.nextToken();
+            }
+
+            tok = new StringTokenizer(System.getProperty(KEYSTORE_TYPE_PROP,
+                config.getProperty(KEYSTORE_TYPE_PROP, KEYSTORE_TYPE_VALUE)), File.pathSeparator);
+
+            m_types = new String[tok.countTokens()];
+
+            for (int i = 0;tok.hasMoreTokens();i++)
+            {
+                m_types[i] = tok.nextToken();
+            }
+        }
+
+        public synchronized Iterator iterator()
+        {
+            if (m_stores == null)
+            {
+                loadStores();
+            }
+
+            return m_stores.iterator();
+        }
+
+        public synchronized int size()
+        {
+            if (m_stores == null)
+            {
+                loadStores();
+            }
+
+            return m_stores.size();
+        }
+
+        private void loadStores()
+        {
+            m_stores = new ArrayList();
+
+            if ((m_keystores.length == m_passwds.length) && (m_passwds.length == m_types.length)
+                && (System.getSecurityManager() != null))
+            {
+                AccessController.doPrivileged(new PrivilegedAction()
+                {
+                    public Object run()
+                    {
+                        List certs = new ArrayList();
+
+                        for (int i = 0;i < m_keystores.length;i++)
+                        {
+
+                            try
+                            {
+                                KeyStore ks = KeyStore.getInstance(m_types[i]);
+                                ks.load(new FileInputStream(m_keystores[i]), m_passwds[i].toCharArray());
+                                for (Enumeration enum = ks.aliases();enum.hasMoreElements();)
+                                {
+                                    String alias = (String) enum.nextElement();
+                                    if (ks.isCertificateEntry(alias))
+                                    {
+                                        certs.add(ks.getCertificate(alias));
+                                    }
+                                }
+                            }
+                            catch (Exception ex)
+                            {
+                                certs.clear();
+                                ex.printStackTrace(System.err);
+
+                                System.err.println("WARNING: Error accessing keystore: " + m_keystores[i]);
+                            }
+
+                            if (!certs.isEmpty())
+                            {
+                                m_stores.addAll(certs);
+                                certs.clear();
+                            }
+                        }
+
+                        return null;
+                    }
+                });
+            }
+            if (m_stores.isEmpty())
+            {
+                System.err.println("WARNING: No trusted CA certificates!");
+            }
+        }
+    }
 }
\ No newline at end of file