FELIX-1626: hack to work around the fact that fileinstall does not load the CM properties soon enough

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@817512 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/assembly/src/main/filtered-resources/etc/config.properties b/karaf/assembly/src/main/filtered-resources/etc/config.properties
index a968995..80439e4 100644
--- a/karaf/assembly/src/main/filtered-resources/etc/config.properties
+++ b/karaf/assembly/src/main/filtered-resources/etc/config.properties
@@ -59,6 +59,13 @@
 felix.fileinstall.poll   = 1000
 
 #
+# Hack for FELIX-1628
+# As fileinstall does not load the properties into CM soon enough,
+# the Main class does this job asap
+#
+karaf.cm.dir=${karaf.base}/etc
+
+#
 # Java platform package export properties.
 #
 
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
index 270ed4a..5a1d524 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
@@ -38,6 +38,8 @@
 import java.util.StringTokenizer;
 import java.util.logging.Logger;
 import java.util.concurrent.CountDownLatch;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
 
 import org.apache.felix.karaf.main.Utils;
 import org.osgi.framework.Bundle;
@@ -112,6 +114,11 @@
     public static final String PROPERTY_CONVERT_TO_MAVEN_URL = "karaf.maven.convert";
 
     /**
+     * ConfigAdmin properties directory
+     */
+    public static final String PROPERTY_CM_DIRECTORY = "karaf.cm.dir";
+
+    /**
      * If a lock should be used before starting the runtime
      */
     public static final String PROPERTY_USE_LOCK = "karaf.lock";
@@ -140,6 +147,7 @@
     private int lockStartLevel = 1;
     private int lockDelay = 1000;
     private boolean exiting = false;
+    private boolean cmProcessed;
 
     public Main(String[] args) {
         this.args = args;
@@ -456,6 +464,7 @@
                                 Bundle b = context.installBundle(parts[0], new URL(parts[1]).openStream());
                                 if (b != null) {
                                     b.start();
+                                    checkCmProperties(b);
                                 }
                             }
                             catch (Exception ex) {
@@ -469,6 +478,59 @@
         }
     }
 
+    /**
+     * TODO: remove this hack when FELIX-1628 is properly implemented
+     * Hack for FELIX-1626.
+     * FileInstall has some delay before installing the configurations which can cause some problems
+     *
+     * @param b
+     */
+    private void checkCmProperties(final Bundle b) {
+        final String cmDir = (String) configProps.get(PROPERTY_CM_DIRECTORY);
+        if (cmProcessed || cmDir == null) {
+            return;
+        }
+        try {
+            // Try to load fileinstall internal classes.
+            // Those are not exported, so this mean if the load succeeds, we have the fileinstall bundle
+            final Class ciClass = b.loadClass("org.apache.felix.fileinstall.internal.ConfigInstaller");
+            final Class fiClass = b.loadClass("org.apache.felix.fileinstall.internal.FileInstall");
+            // If we have been able to load the classes, start a thread that will wait until
+            // fileinstall is correctly configured using config admin and push all configs.
+            new Thread() {
+                public void run() {
+                    for (int i = 0; !cmProcessed && i < 100; i++) {
+                        try {
+                            Thread.sleep(50);
+                            Method mth = fiClass.getDeclaredMethod("getConfigurationAdmin", long.class);
+                            mth.setAccessible(true);
+                            if (mth.invoke(null, 0) != null) {
+                                Constructor cns = ciClass.getDeclaredConstructor(BundleContext.class);
+                                cns.setAccessible(true);
+                                Object ci = cns.newInstance(b.getBundleContext());
+                                mth = ciClass.getDeclaredMethod("setConfig", File.class);
+                                mth.setAccessible(true);
+                                cmProcessed = true;
+//                                System.err.println("Found ready FileInstall");
+                                for (File f : new File(cmDir).listFiles()) {
+                                    if (f.getName().endsWith(".cfg")) {
+//                                        System.err.println("Processing: " + f.getName());
+                                        mth.invoke(ci, f);
+                                    }
+                                }
+                            }
+                        } catch (Throwable t) {
+                            if (cmProcessed) {
+                                t.printStackTrace();
+                            }
+                        }
+                    }
+                }
+            }.start();
+        } catch (Throwable t) {
+        }
+    }
+
     private static String[] convertToMavenUrlsIfNeeded(String location, boolean convertToMavenUrls) {
         String[] parts = location.split("\\|");
         if (convertToMavenUrls) {