FELIX-1111: allow karaf to run on equinox

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@771836 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/assembly/pom.xml b/karaf/assembly/pom.xml
index c9f4cc0..0f5f22b 100644
--- a/karaf/assembly/pom.xml
+++ b/karaf/assembly/pom.xml
@@ -230,6 +230,14 @@
             <groupId>com.oracle.osgi</groupId>
             <artifactId>jmx-impl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse</groupId>
+            <artifactId>osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <resources>
diff --git a/karaf/assembly/src/main/descriptors/unix-bin.xml b/karaf/assembly/src/main/descriptors/unix-bin.xml
index 5363a46..c802940 100644
--- a/karaf/assembly/src/main/descriptors/unix-bin.xml
+++ b/karaf/assembly/src/main/descriptors/unix-bin.xml
@@ -124,6 +124,7 @@
                 <include>org.apache.felix:org.osgi.compendium</include>
                 <include>org.apache.felix:org.apache.felix.configadmin</include>
                 <include>org.apache.felix:org.apache.felix.prefs</include>
+                <include>org.apache.felix:org.apache.felix.framework</include>
             </includes>
         </dependencySet>
         <dependencySet>
@@ -287,6 +288,15 @@
                 <include>com.oracle.osgi:jmx-impl</include>
             </includes>
         </dependencySet>
+        <dependencySet>
+            <outputDirectory>/system</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <outputFileNameMapping>org/eclipse/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+            <includes>
+                <include>org.eclipse:osgi</include>
+            </includes>
+        </dependencySet>
 
     </dependencySets>
 
diff --git a/karaf/assembly/src/main/descriptors/windows-bin.xml b/karaf/assembly/src/main/descriptors/windows-bin.xml
index 59e1068..d920cb9 100644
--- a/karaf/assembly/src/main/descriptors/windows-bin.xml
+++ b/karaf/assembly/src/main/descriptors/windows-bin.xml
@@ -116,6 +116,7 @@
                 <include>org.apache.felix:org.osgi.compendium</include>
                 <include>org.apache.felix:org.apache.felix.configadmin</include>
                 <include>org.apache.felix:org.apache.felix.prefs</include>
+                <include>org.apache.felix:org.apache.felix.framework</include>
             </includes>
         </dependencySet>
         <dependencySet>
@@ -279,6 +280,15 @@
                 <include>com.oracle.osgi:jmx-impl</include>
             </includes>
         </dependencySet>
+        <dependencySet>
+            <outputDirectory>/system</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <outputFileNameMapping>org/eclipse/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+            <includes>
+                <include>org.eclipse:osgi</include>
+            </includes>
+        </dependencySet>
 
     </dependencySets>
 
diff --git a/karaf/assembly/src/main/distribution/unix-shell/bin/karaf b/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
index 4016399..e58b22b 100755
--- a/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
+++ b/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
@@ -281,7 +281,7 @@
         KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"`
         KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"`
     fi
-    exec $JAVA $JAVA_OPTS -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" org.apache.felix.karaf.main.Main $*
+    exec $JAVA $JAVA_OPTS -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" org.apache.felix.karaf.main.Bootstrap $*
 }
 
 main() {
diff --git a/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat b/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat
index 189dd1c..8f62396 100755
--- a/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat
+++ b/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat
@@ -152,7 +152,7 @@
     if "%SHIFT%" == "true" SET ARGS=%2 %3 %4 %5 %6 %7 %8
     if not "%SHIFT%" == "true" SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8    
     rem Execute the Java Virtual Machine
-    "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Djava.util.logging.config.file=%KARAF_BASE%\etc\java.util.logging.properties org.apache.felix.karaf.main.Main %ARGS%
+    "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Djava.util.logging.config.file=%KARAF_BASE%\etc\java.util.logging.properties org.apache.felix.karaf.main.Bootstrap %ARGS%
 
 rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
diff --git a/karaf/assembly/src/main/filtered-resources/etc/config.properties b/karaf/assembly/src/main/filtered-resources/etc/config.properties
index dbe5629..89ffff5 100644
--- a/karaf/assembly/src/main/filtered-resources/etc/config.properties
+++ b/karaf/assembly/src/main/filtered-resources/etc/config.properties
@@ -18,6 +18,14 @@
 ################################################################################
 
 #
+# Framework selection properties
+#
+karaf.framework=equinox
+
+karaf.framework.equinox=system/org/eclipse/osgi/${equinox.version}/osgi-${equinox.version}.jar
+karaf.framework.felix=system/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar
+
+#
 # Framework config properties.
 #
 org.osgi.framework.system.packages=org.osgi.framework; version=1.4.0, \
@@ -26,7 +34,6 @@
  org.osgi.service.startlevel; version=1.1.0, \
  org.osgi.service.url; version=1.0.0, \
  org.osgi.util.tracker; version=1.3.3, \
- org.apache.felix.karaf.main.spi; version=${karaf.osgi.version}, \
  org.apache.felix.karaf.jaas.boot; version=${karaf.osgi.version}, \
  org.apache.felix.karaf.version; version=${karaf.osgi.version}, \
  ${jre-${java.specification.version}}
diff --git a/karaf/gshell/gshell-core/pom.xml b/karaf/gshell/gshell-core/pom.xml
index 7b5d410..d06580b 100644
--- a/karaf/gshell/gshell-core/pom.xml
+++ b/karaf/gshell/gshell-core/pom.xml
@@ -39,10 +39,6 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.felix.karaf</groupId>
-            <artifactId>org.apache.felix.karaf.main</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.felix.karaf.jaas</groupId>
             <artifactId>org.apache.felix.karaf.jaas.config</artifactId>
         </dependency>
@@ -167,6 +163,16 @@
             <groupId>org.apache.servicemix.bundles</groupId>
             <artifactId>org.apache.servicemix.bundles.jline</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/karaf/main/pom.xml b/karaf/main/pom.xml
index adf6fd2..87eef1d 100644
--- a/karaf/main/pom.xml
+++ b/karaf/main/pom.xml
@@ -35,12 +35,14 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.framework</artifactId>
+            <groupId>org.eclipse</groupId>
+            <artifactId>osgi</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
-            <artifactId>org.osgi.core</artifactId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.servicemix.bundles</groupId>
@@ -61,24 +63,20 @@
                         <Bundle-Description>OSGi R4 framework.</Bundle-Description>
                         <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                         <Export-Package>org.apache.felix.karaf.main.spi.*;version=${pom.version}</Export-Package>
+                        <!--
                         <Private-Package>
-                            org.apache.felix.karaf.main;-split-package:=merge-first,
-                            org.apache.felix.moduleloader.*;-split-package:=merge-first,
-                            org.apache.felix.framework.*;-split-package:=merge-first,
-                            org.osgi.framework.launch*,
-                            org.osgi.framework.hooks*,
-                            org.osgi.framework;-split-package:=merge-first,
-                            org.osgi.service.packageadmin;-split-package:=merge-first,
-                            org.osgi.service.startlevel;-split-package:=merge-first,
-                            org.osgi.service.url;-split-package:=merge-first,
-                            org.osgi.util.tracker;-split-package:=merge-first,
+                            org.apache.felix.*;-split-package:=merge-first,
+                            org.eclipse.*;-split-package:=merge-first,
+                            org.osgi.*;-split-package:=merge-first,
                             META-INF;-split-package:=merge-first
                         </Private-Package>
                         <Import-Package>!*</Import-Package>
+                        -->
                     </instructions>
                     <unpackBundle>true</unpackBundle>
                 </configuration>
             </plugin>
+            <!--
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
@@ -91,24 +89,25 @@
                         <configuration>
                             <artifactSet>
                                 <includes>
+                                    <include>org.eclipse:osgi</include>
                                     <include>org.apache.felix:org.apache.felix.framework</include>
-                                    <include>org.apache.felix:org.osgi.core</include>
                                     <include>${project.groupId}:${project.artifactId}</include>
                                 </includes>
                             </artifactSet>
                             <filters>
                                 <filter>
-                                    <artifact>org.apache.felix:org.apache.felix.framework</artifact>
-                                    <excludes>
-                                        <exclude>org/apache/felix/**</exclude>
-                                        <exclude>org/osgi/**</exclude>
-                                    </excludes>
+                                    <artifact>org.eclipse:osgi</artifact>
+                                    <includes>
+                                        <include>org/osgi/**</include>
+                                        <include>org/eclipse/**</include>
+                                        <include>hookconfigurators.properties</include>
+                                    </includes>
                                 </filter>
                                 <filter>
-                                    <artifact>org.apache.felix:org.osgi.core</artifact>
-                                    <excludes>
-                                        <exclude>org/osgi/**</exclude>
-                                    </excludes>
+                                    <artifact>org.apache.felix:org.apache.felix.framework</artifact>
+                                    <includes>
+                                        <include>org/apache/felix/**</include>
+                                    </includes>
                                 </filter>
                             </filters>
                             <createSourcesJar>${createSourcesJar}</createSourcesJar>
@@ -118,6 +117,7 @@
                     </execution>
                 </executions>
             </plugin>
+        -->
         </plugins>
         <resources>
             <resource>
@@ -148,6 +148,11 @@
                                 <configuration>
                                     <artifactItems>
                                         <artifactItem>
+                                            <groupId>org.eclipse</groupId>
+                                            <artifactId>osgi</artifactId>
+                                            <classifier>sources</classifier>
+                                        </artifactItem>
+                                        <artifactItem>
                                             <groupId>org.apache.felix</groupId>
                                             <artifactId>org.osgi.core</artifactId>
                                             <classifier>sources</classifier>
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Bootstrap.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Bootstrap.java
new file mode 100644
index 0000000..86b6a2f
--- /dev/null
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Bootstrap.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.karaf.main;
+
+import java.util.Properties;
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileNotFoundException;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.lang.reflect.Method;
+
+public class Bootstrap {
+
+    public static final String FRAMEWORK_PROPERTIES_FILE_NAME = "config.properties";
+
+    public static final String KARAF_FRAMEWORK = "karaf.framework";
+
+    public static void main(String[] args) {
+        try {
+            File home = Utils.getKarafHome();
+            File file = new File(new File(home, "etc"), FRAMEWORK_PROPERTIES_FILE_NAME);
+            if (!file.exists()) {
+                throw new FileNotFoundException(file.getAbsolutePath());
+            }
+            Properties props = new Properties();
+            InputStream is = new FileInputStream(file);
+            props.load(is);
+            is.close();
+
+            String framework = props.getProperty(KARAF_FRAMEWORK);
+            if (framework == null) {
+                throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + " must be set in the etc/" + FRAMEWORK_PROPERTIES_FILE_NAME + " configuration file");
+            }
+            String bundle = props.getProperty(KARAF_FRAMEWORK + "." + framework);
+            if (bundle == null) {
+                throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + "." + framework + " must be set in the etc/" + FRAMEWORK_PROPERTIES_FILE_NAME + " configuration file");
+            }
+            File bundleFile = new File(home, bundle);
+            if (!bundleFile.exists()) {
+                throw new FileNotFoundException(bundleFile.getAbsolutePath());
+            }
+
+            URLClassLoader classLoader = (URLClassLoader) Bootstrap.class.getClassLoader();
+            Method mth = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+            mth.setAccessible(true);
+            mth.invoke(classLoader, bundleFile.toURL());
+
+            Main.main(args);
+
+        } catch (Throwable t) {
+            t.printStackTrace();
+            System.exit(-1);
+        }
+    }
+}
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 66bac66..174e703 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
@@ -22,33 +22,29 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.JarURLConnection;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
 import java.net.MalformedURLException;
-import java.net.URI;
 import java.net.URL;
+import java.net.URLClassLoader;
 import java.security.Provider;
 import java.security.Security;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
 
-import org.apache.felix.framework.Felix;
-import org.apache.felix.framework.cache.BundleCache;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.karaf.main.spi.MainService;
+import org.apache.felix.karaf.main.Utils;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
 import org.osgi.service.startlevel.StartLevel;
 
 /**
@@ -62,7 +58,7 @@
  * the framework.
  * </p>
  */
-public class Main implements MainService, BundleActivator {
+public class Main {
     /**
      * The default name used for the system properties file.
      */
@@ -130,17 +126,15 @@
 
     public static final String PROPERTY_LOCK_CLASS_DEFAULT = SimpleFileLock.class.getName();
 
-
     private File karafHome;
     private File karafBase;
-    private static Properties m_configProps = null;
-    private static Felix m_felix = null;
+    private Properties configProps = null;
+    private Framework framework = null;
     private final String[] args;
     private int exitCode;
     private Lock lock;
-    private CountDownLatch shutdown = new CountDownLatch(1);
     private int defaultStartLevel = 100;
-    private int lockStartLevel = 0;
+    private int lockStartLevel = 1;
     private int lockDelay = 1000;
     private boolean exiting = false;
 
@@ -149,8 +143,8 @@
     }
 
     public void launch() throws Exception {
-        karafHome = getServiceMixHome();
-        karafBase = getServiceMixBase(karafHome);
+        karafHome = Utils.getKarafHome();
+        karafBase = getKarafBase(karafHome);
 
         //System.out.println("Karaf Home: "+main.servicemixHome.getPath());
         //System.out.println("Karaf Base: "+main.servicemixBase.getPath());
@@ -162,47 +156,34 @@
         loadSystemProperties();
 
         // Read configuration properties.
-        m_configProps = loadConfigProperties();
+        configProps = loadConfigProperties();
 
         // Copy framework properties from the system properties.
-        Main.copySystemProperties(m_configProps);
+        Main.copySystemProperties(configProps);
 
-        processSecurityProperties(m_configProps);
+        processSecurityProperties(configProps);
 
-        m_configProps.setProperty(BundleCache.CACHE_ROOTDIR_PROP, karafBase.getPath() + "/data");
-        m_configProps.setProperty(Constants.FRAMEWORK_STORAGE, "cache");
-
-        // Register the Main class so that other bundles can inspect the command line args.
-        BundleActivator activator = new BundleActivator() {
-            private ServiceRegistration registration;
-
-            public void start(BundleContext context) {
-                registration = context.registerService(MainService.class.getName(), Main.this, null);
-            }
-
-            public void stop(BundleContext context) {
-                registration.unregister();
-                shutdown.countDown();
-            }
-        };
-        List<BundleActivator> activations = new ArrayList<BundleActivator>();
-        activations.add(this);
-        activations.add(activator);
-
-        m_configProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, activations);
+        File storage = new File(karafBase.getPath(), "data/cache");
+        storage.mkdirs();
+        configProps.setProperty(Constants.FRAMEWORK_STORAGE, storage.getAbsolutePath());
 
         try {
-            defaultStartLevel = Integer.parseInt(m_configProps.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
-            lockStartLevel = Integer.parseInt(m_configProps.getProperty(PROPERTY_LOCK_LEVEL, Integer.toString(lockStartLevel)));
-            lockDelay = Integer.parseInt(m_configProps.getProperty(PROPERTY_LOCK_DELAY, Integer.toString(lockDelay)));
-            m_configProps.setProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, Integer.toString(lockStartLevel));
+            defaultStartLevel = Integer.parseInt(configProps.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
+            lockStartLevel = Integer.parseInt(configProps.getProperty(PROPERTY_LOCK_LEVEL, Integer.toString(lockStartLevel)));
+            lockDelay = Integer.parseInt(configProps.getProperty(PROPERTY_LOCK_DELAY, Integer.toString(lockDelay)));
+            configProps.setProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, Integer.toString(lockStartLevel));
             // Start up the OSGI framework
-            m_felix = new Felix(new StringMap(m_configProps, false));
-            m_felix.start();
+
+            InputStream is = getClass().getResourceAsStream("/META-INF/services/" + FrameworkFactory.class.getName());
+            String factoryClass = new BufferedReader(new InputStreamReader(is, "UTF-8")).readLine();
+            FrameworkFactory factory = (FrameworkFactory) getClass().getClassLoader().loadClass(factoryClass).newInstance();
+            framework = factory.newFramework(new StringMap(configProps, false));
+            framework.start();
+            processAutoProperties(framework.getBundleContext());
             // Start lock monitor
             new Thread() {
                 public void run() {
-                    lock(m_configProps);
+                    lock(configProps);
                 }
             }.start();
         }
@@ -215,11 +196,11 @@
     public void destroy(boolean await) throws Exception {
         try {
             if (await) {
-                shutdown.await();
+                framework.waitForStop(0);
             }
             exiting = true;
-            if (m_felix.getState() == Bundle.ACTIVE) {
-                m_felix.stop();
+            if (framework.getState() == Bundle.ACTIVE) {
+                framework.stop();
             }
         } finally {
             unlock();
@@ -227,26 +208,6 @@
     }
 
     /**
-     * Used to instigate auto-install and auto-start configuration
-     * property processing via a custom framework activator during
-     * framework startup.
-     *
-     * @param context The system bundle context.
-     */
-    public void start(BundleContext context) {
-        Main.processAutoProperties(context);
-    }
-
-    /**
-     * Currently does nothing as part of framework shutdown.
-     *
-     * @param context The system bundle context.
-     */
-    public void stop(BundleContext context) {
-        // Do nothing.
-    }
-
-    /**
      * <p>
      * This method performs the main task of constructing an framework instance
      * and starting its execution. The following functions are performed
@@ -337,81 +298,18 @@
         }
     }
 
-    private static File getServiceMixHome() throws IOException {
-        File rc = null;
-
-        // Use the system property if specified.
-        String path = System.getProperty(PROP_KARAF_HOME);
-        if (path != null) {
-            rc = validateDirectoryExists(path, "Invalid " + PROP_KARAF_HOME + " system property");
-        }
-
-        if (rc == null) {
-            path = System.getenv(ENV_KARAF_HOME);
-            if (path != null) {
-                rc = validateDirectoryExists(path, "Invalid " + ENV_KARAF_HOME + " environment variable");
-            }
-        }
-
-        // Try to figure it out using the jar file this class was loaded from.
-        if (rc == null) {
-            // guess the home from the location of the jar
-            URL url = Main.class.getClassLoader().getResource(Main.class.getName().replace(".", "/") + ".class");
-            if (url != null) {
-                try {
-                    JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
-                    url = jarConnection.getJarFileURL();
-                    rc = new File(new URI(url.toString())).getCanonicalFile().getParentFile().getParentFile();
-                } catch (Exception ignored) {
-                }
-            }
-        }
-
-        if (rc == null) {
-            // Dig into the classpath to guess the location of the jar
-            String classpath = System.getProperty("java.class.path");
-            int index = classpath.toLowerCase().indexOf("karaf.jar");
-            int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
-            if (index >= start) {
-                String jarLocation = classpath.substring(start, index);
-                rc = new File(jarLocation).getCanonicalFile().getParentFile();
-            }
-        }
-        if (rc == null) {
-            throw new IOException("The Karaf install directory could not be determined.  Please set the " + PROP_KARAF_HOME + " system property or the " + ENV_KARAF_HOME + " environment variable.");
-        }
-
-        return rc;
-    }
-
-    private static File validateDirectoryExists(String path, String errPrefix) {
-        File rc;
-        try {
-            rc = new File(path).getCanonicalFile();
-        } catch (IOException e) {
-            throw new IllegalArgumentException(errPrefix + " '" + path + "' : " + e.getMessage());
-        }
-        if (!rc.exists()) {
-            throw new IllegalArgumentException(errPrefix + " '" + path + "' : does not exist");
-        }
-        if (!rc.isDirectory()) {
-            throw new IllegalArgumentException(errPrefix + " '" + path + "' : is not a directory");
-        }
-        return rc;
-    }
-
-    private static File getServiceMixBase(File defaultValue) {
+    private static File getKarafBase(File defaultValue) {
         File rc = null;
 
         String path = System.getProperty(PROP_KARAF_BASE);
         if (path != null) {
-            rc = validateDirectoryExists(path, "Invalid " + PROP_KARAF_BASE + " system property");
+            rc = Utils.validateDirectoryExists(path, "Invalid " + PROP_KARAF_BASE + " system property");
         }
 
         if (rc == null) {
             path = System.getenv(ENV_KARAF_BASE);
             if (path != null) {
-                rc = validateDirectoryExists(path, "Invalid " + ENV_KARAF_BASE + " environment variable");
+                rc = Utils.validateDirectoryExists(path, "Invalid " + ENV_KARAF_BASE + " environment variable");
             }
         }
 
@@ -440,9 +338,9 @@
      * Processes the auto-install and auto-start properties from the
      * specified configuration properties.
      */
-    private static void processAutoProperties(BundleContext context) {
+    private void processAutoProperties(BundleContext context) {
         // Check if we want to convert URLs to maven style
-        boolean convertToMavenUrls = Boolean.parseBoolean(m_configProps.getProperty(PROPERTY_CONVERT_TO_MAVEN_URL, "true"));
+        boolean convertToMavenUrls = Boolean.parseBoolean(configProps.getProperty(PROPERTY_CONVERT_TO_MAVEN_URL, "true"));
 
         // Retrieve the Start Level service, since it will be needed
         // to set the start level of the installed bundles.
@@ -454,7 +352,7 @@
         // the start level to which the bundles are assigned is specified by
         // appending a ".n" to the auto-install property name, where "n" is
         // the desired start level for the list of bundles.
-        for (Iterator i = m_configProps.keySet().iterator(); i.hasNext();) {
+        for (Iterator i = configProps.keySet().iterator(); i.hasNext();) {
             String key = (String) i.next();
 
             // Ignore all keys that are not the auto-install property.
@@ -475,7 +373,7 @@
                 }
             }
 
-            StringTokenizer st = new StringTokenizer(m_configProps.getProperty(key), "\" ", true);
+            StringTokenizer st = new StringTokenizer(configProps.getProperty(key), "\" ", true);
             if (st.countTokens() > 0) {
                 String location = null;
                 do {
@@ -502,7 +400,7 @@
         // where "n" is the desired start level for the list of bundles.
         // The following code starts bundles in two passes, first it installs
         // them, then it starts them.
-        for (Iterator i = m_configProps.keySet().iterator(); i.hasNext();) {
+        for (Iterator i = configProps.keySet().iterator(); i.hasNext();) {
             String key = (String) i.next();
 
             // Ignore all keys that are not the auto-start property.
@@ -523,7 +421,7 @@
                 }
             }
 
-            StringTokenizer st = new StringTokenizer(m_configProps.getProperty(key), "\" ", true);
+            StringTokenizer st = new StringTokenizer(configProps.getProperty(key), "\" ", true);
             if (st.countTokens() > 0) {
                 String location = null;
                 do {
@@ -544,10 +442,10 @@
         }
 
         // Now loop through and start the installed bundles.
-        for (Iterator i = m_configProps.keySet().iterator(); i.hasNext();) {
+        for (Iterator i = configProps.keySet().iterator(); i.hasNext();) {
             String key = (String) i.next();
             if (key.startsWith(PROPERTY_AUTO_START)) {
-                StringTokenizer st = new StringTokenizer(m_configProps.getProperty(key), "\" ", true);
+                StringTokenizer st = new StringTokenizer(configProps.getProperty(key), "\" ", true);
                 if (st.countTokens() > 0) {
                     String location = null;
                     do {
@@ -1091,14 +989,6 @@
         this.exitCode = exitCode;
     }
 
-    public File getKarafHome() {
-        return karafHome;
-    }
-
-    public File getKarafBase() {
-        return karafBase;
-    }
-
     public void lock(Properties props) {
         try {
             if (Boolean.parseBoolean(props.getProperty(PROPERTY_USE_LOCK, "true"))) {
@@ -1117,7 +1007,7 @@
                             }
                             Thread.sleep(lockDelay);
                         }
-                        if (m_felix.getState() == Bundle.ACTIVE && !exiting) {
+                        if (framework.getState() == Bundle.ACTIVE && !exiting) {
                             System.out.println("Lost the lock, stopping this instance ...");
                             setStartLevel(lockStartLevel);
                         }
@@ -1141,7 +1031,7 @@
     }
 
     protected void setStartLevel(int level) throws Exception {
-        BundleContext ctx = m_felix.getBundleContext();
+        BundleContext ctx = framework.getBundleContext();
         ServiceReference[] refs = ctx.getServiceReferences(StartLevel.class.getName(), null);
         StartLevel sl = (StartLevel) ctx.getService(refs[0]);
         sl.setStartLevel(level);
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/StringMap.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/StringMap.java
new file mode 100644
index 0000000..ce6e00d
--- /dev/null
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/StringMap.java
@@ -0,0 +1,95 @@
+/*
+ * 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.karaf.main;
+
+import java.util.*;
+
+/**
+ * Simple utility class that creates a map for string-based keys by
+ * extending <tt>TreeMap</tt>. This map can be set to use case-sensitive
+ * or case-insensitive comparison when searching for the key.
+ * Any keys put into this map will be converted to
+ * a <tt>String</tt> using the <tt>toString()</tt> method,
+ * since it is only intended to compare strings.
+**/
+public class StringMap extends TreeMap
+{
+    public StringMap()
+    {
+        this(true);
+    }
+
+    public StringMap(boolean caseSensitive)
+    {
+        super(new StringComparator(caseSensitive));
+    }
+
+    public StringMap(Map map, boolean caseSensitive)
+    {
+        this(caseSensitive);
+        putAll(map);
+    }
+
+    public Object put(Object key, Object value)
+    {
+        return super.put(key.toString(), value);
+    }
+
+    public boolean isCaseSensitive()
+    {
+        return ((StringComparator) comparator()).isCaseSensitive();
+    }
+
+    public void setCaseSensitive(boolean b)
+    {
+        ((StringComparator) comparator()).setCaseSensitive(b);
+    }
+
+    private static class StringComparator implements Comparator
+    {
+        private boolean m_isCaseSensitive = true;
+
+        public StringComparator(boolean b)
+        {
+            m_isCaseSensitive = b;
+        }
+
+        public int compare(Object o1, Object o2)
+        {
+            if (m_isCaseSensitive)
+            {
+                return o1.toString().compareTo(o2.toString());
+            }
+            else
+            {
+                return o1.toString().compareToIgnoreCase(o2.toString());
+            }
+        }
+
+        public boolean isCaseSensitive()
+        {
+            return m_isCaseSensitive;
+        }
+
+        public void setCaseSensitive(boolean b)
+        {
+            m_isCaseSensitive = b;
+        }
+    }
+}
\ No newline at end of file
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Utils.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Utils.java
new file mode 100644
index 0000000..db8fad7
--- /dev/null
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Utils.java
@@ -0,0 +1,93 @@
+/*
+ * 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.karaf.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.JarURLConnection;
+import java.net.URI;
+
+import org.apache.felix.karaf.main.Main;
+
+public class Utils {
+
+    public static File getKarafHome() throws IOException {
+        File rc = null;
+
+        // Use the system property if specified.
+        String path = System.getProperty(Main.PROP_KARAF_HOME);
+        if (path != null) {
+            rc = validateDirectoryExists(path, "Invalid " + Main.PROP_KARAF_HOME + " system property");
+        }
+
+        if (rc == null) {
+            path = System.getenv(Main.ENV_KARAF_HOME);
+            if (path != null) {
+                rc = validateDirectoryExists(path, "Invalid " + Main.ENV_KARAF_HOME + " environment variable");
+            }
+        }
+
+        // Try to figure it out using the jar file this class was loaded from.
+        if (rc == null) {
+            // guess the home from the location of the jar
+            URL url = Main.class.getClassLoader().getResource(Main.class.getName().replace(".", "/") + ".class");
+            if (url != null) {
+                try {
+                    JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
+                    url = jarConnection.getJarFileURL();
+                    rc = new File(new URI(url.toString())).getCanonicalFile().getParentFile().getParentFile();
+                } catch (Exception ignored) {
+                }
+            }
+        }
+
+        if (rc == null) {
+            // Dig into the classpath to guess the location of the jar
+            String classpath = System.getProperty("java.class.path");
+            int index = classpath.toLowerCase().indexOf("karaf.jar");
+            int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
+            if (index >= start) {
+                String jarLocation = classpath.substring(start, index);
+                rc = new File(jarLocation).getCanonicalFile().getParentFile();
+            }
+        }
+        if (rc == null) {
+            throw new IOException("The Karaf install directory could not be determined.  Please set the " + Main.PROP_KARAF_HOME + " system property or the " + Main.ENV_KARAF_HOME + " environment variable.");
+        }
+
+        return rc;
+    }
+
+    public static File validateDirectoryExists(String path, String errPrefix) {
+        File rc;
+        try {
+            rc = new File(path).getCanonicalFile();
+        } catch (IOException e) {
+            throw new IllegalArgumentException(errPrefix + " '" + path + "' : " + e.getMessage());
+        }
+        if (!rc.exists()) {
+            throw new IllegalArgumentException(errPrefix + " '" + path + "' : does not exist");
+        }
+        if (!rc.isDirectory()) {
+            throw new IllegalArgumentException(errPrefix + " '" + path + "' : is not a directory");
+        }
+        return rc;
+    }
+}
diff --git a/karaf/pom.xml b/karaf/pom.xml
index 50520e9..1c8acf4 100644
--- a/karaf/pom.xml
+++ b/karaf/pom.xml
@@ -75,6 +75,7 @@
         <commons.vfs.version>1.0_1</commons.vfs.version>
         <depends.maven.plugin.version>1.0</depends.maven.plugin.version>
         <easymock.version>2.4</easymock.version>
+        <equinox.version> 3.5.0.v20090429-1630</equinox.version>
         <felix.configadmin.version>1.0.4</felix.configadmin.version>
         <felix.plugin.version>2.0.0</felix.plugin.version>
         <felix.framework.version>1.6.0</felix.framework.version>
@@ -85,7 +86,7 @@
         <geronimo.annotation.version>1.1.1</geronimo.annotation.version>
         <geronimo.servlet.version>1.1.2</geronimo.servlet.version>
         <gshell.version>1.0-alpha-2</gshell.version>
-        <jaxp.ri.version>1.4.2_1</jaxp.ri.version>
+        <jaxp.ri.version>1.4.2_2</jaxp.ri.version>
         <junit.version>3.8.2_1</junit.version>
         <jline.version>0.9.94_1</jline.version>
         <log4j.version>1.2.14</log4j.version>
@@ -817,6 +818,11 @@
                 <artifactId>pax-exam-junit-extender-impl</artifactId>
                 <version>${pax.exam.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.eclipse</groupId>
+                <artifactId>osgi</artifactId>
+                <version>${equinox.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>