You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2011/04/27 01:16:30 UTC

svn commit: r1096949 [1/2] - in /geronimo/server/trunk: ./ framework/buildsupport/car-maven-plugin/ framework/buildsupport/car-maven-plugin/src/main/filtered-resources/ framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/ fram...

Author: djencks
Date: Tue Apr 26 23:16:30 2011
New Revision: 1096949

URL: http://svn.apache.org/viewvc?rev=1096949&view=rev
Log:
start working on a karaf-like framework starter for car-maven-plugin

Added:
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties   (with props)
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java   (with props)
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java   (with props)
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/ThreadLocalProperties.java   (with props)
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/test/java/org/apache/geronimo/mavenplugins/car/FrameworkHelperTest.java   (with props)
Modified:
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml
    geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/resources/META-INF/plexus/components.xml
    geronimo/server/trunk/framework/modules/geronimo-kernel/pom.xml
    geronimo/server/trunk/framework/modules/geronimo-system/pom.xml
    geronimo/server/trunk/framework/modules/geronimo-system/src/main/java/org/apache/geronimo/system/main/MainBridge.java
    geronimo/server/trunk/framework/modules/geronimo-system/src/main/java/org/apache/geronimo/system/osgi/BootActivator.java
    geronimo/server/trunk/pom.xml

Modified: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml?rev=1096949&r1=1096948&r2=1096949&view=diff
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml (original)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml Tue Apr 26 23:16:30 2011
@@ -160,11 +160,21 @@
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-plugin-api</artifactId>
-            <version>2.2.1</version>
+            <version>3.0</version>
             <scope>provided</scope>
         </dependency>
 
         <dependency>
+           <groupId>org.sonatype.aether</groupId>
+           <artifactId>aether-api</artifactId>
+           <version>1.8</version>
+         </dependency>
+         <dependency>
+           <groupId>org.sonatype.aether</groupId>
+           <artifactId>aether-util</artifactId>
+           <version>1.8</version>
+         </dependency>
+         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-archiver</artifactId>
             <version>2.2</version>
@@ -281,6 +291,15 @@
                     <groupId>org.apache.felix</groupId>
                     <artifactId>org.apache.felix.framework</artifactId>
                 </dependency>
+                <!--<dependency>-->
+                    <!--<groupId>org.apache.karaf</groupId>-->
+                    <!--<artifactId>org.apache.karaf.main</artifactId>-->
+                <!--</dependency>-->
+                <dependency>
+                    <groupId>org.apache.karaf.assemblies.features</groupId>
+                    <artifactId>karaf-framework</artifactId>
+                    <type>kar</type>
+                </dependency>
             </dependencies>
 
         </profile>
@@ -300,10 +319,103 @@
                     <groupId>org.eclipse</groupId>
                     <artifactId>osgi</artifactId>
                 </dependency>
+                <!--<dependency>-->
+                    <!--<groupId>org.apache.karaf</groupId>-->
+                    <!--<artifactId>org.apache.karaf.main</artifactId>-->
+                <!--</dependency>-->
+                <dependency>
+                    <groupId>org.apache.karaf.assemblies.features</groupId>
+                    <artifactId>karaf-framework</artifactId>
+                    <type>kar</type>
+                </dependency>
             </dependencies>
 
         </profile>
     </profiles>
+    <build>
+        <plugins>
+<!--    This causes a class cast exception
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                  <execution>
+                    <id>unpack</id>
+                    <phase>generate-resources</phase>
+                    <goals>
+                      <goal>unpack</goal>
+                    </goals>
+                    <configuration>
+                      <artifactItems>
+                        <artifactItem>
+                            <groupId>org.apache.karaf.assemblies.features</groupId>
+                            <artifactId>karaf-framework</artifactId>
+                            <type>kar</type>
+                          <overWrite>false</overWrite>
+                          <outputDirectory>${project.build.directory}/classes</outputDirectory>
+                          <includes>resources/etc/**</includes>
+                        </artifactItem>
+                      </artifactItems>
+                    </configuration>
+                  </execution>
+                </executions>
+            </plugin>
+-->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                  <execution>
+                    <id>copy</id>
+                    <phase>generate-resources</phase>
+                    <goals>
+                      <goal>copy</goal>
+                    </goals>
+                    <configuration>
+                      <artifactItems>
+                        <artifactItem>
+                            <groupId>org.apache.karaf.assemblies.features</groupId>
+                            <artifactId>karaf-framework</artifactId>
+                            <type>kar</type>
+                          <!--<overWrite>false</overWrite>-->
+                          <!--<outputDirectory>${project.build.directory}/classes</outputDirectory>-->
+                          <!--<includes>resources/etc/**</includes>-->
+                        </artifactItem>
+                      </artifactItems>
+                        <stripVersion>true</stripVersion>
+                    </configuration>
+                  </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.6</version>
+                <executions>
+                  <execution>
+                    <phase>process-resources</phase>
+                    <configuration>
+                      <target>
+                          <unzip src="${project.build.directory}/dependency/karaf-framework.kar"
+                                 dest="${project.build.directory}/classes">
+                              <patternset>
+                                  <include name="resources/etc/**"/>
+                                  <exclude name="resources/etc/startup.properties"/>
+                              </patternset>
+                          </unzip>
+
+                      </target>
+                    </configuration>
+                    <goals>
+                      <goal>run</goal>
+                    </goals>
+                  </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
 

Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties Tue Apr 26 23:16:30 2011
@@ -0,0 +1,97 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+# This file allows you to control the start level of each bundle.
+#
+
+#
+# Startup core services like logging
+#
+org.ops4j.pax.url\:pax-url-mvn\:${pax.url.version}=5
+org.ops4j.pax.url\:pax-url-wrap\:${pax.url.version}=5
+org.ops4j.pax.logging\:pax-logging-api\:${pax.logging.version}=8
+org.ops4j.pax.logging\:pax-logging-service\:${pax.logging.version}=8
+org.apache.felix\:org.apache.felix.configadmin\:${felix.configadmin.version}=10
+org.apache.felix\:org.apache.felix.fileinstall\:${felix.fileinstall.version}=11
+
+#
+# The rest of the services..
+#
+org.apache.servicemix.bundles\:org.apache.servicemix.bundles.asm\:${asm.bundle.version}=20
+org.apache.aries\:org.apache.aries.util\:${aries.util.version}=20
+org.apache.aries.proxy\:org.apache.aries.proxy\:${aries.proxy.version}=20
+org.apache.aries.blueprint\:org.apache.aries.blueprint\:${aries.blueprint.version}=20
+
+org.apache.karaf.shell\:org.apache.karaf.shell.console\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.osgi\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.log\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.packages\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.commands\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.dev\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.config\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.modules\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.command\:${karaf.version}=30
+org.apache.karaf.features\:org.apache.karaf.features.core\:${karaf.version}=30
+org.apache.karaf.features\:org.apache.karaf.features.command\:${karaf.version}=30
+#org.apache.karaf.features\:org.apache.karaf.features.management\:${karaf.version}=30
+
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.core\:${karaf.version}=30
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.common\:${karaf.version}=30
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.command\:${karaf.version}=30
+#org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.management\:${karaf.version}=30
+
+#org.apache.karaf\:org.apache.karaf.management\:${karaf.version}=30
+#org.apache.aries.jmx\:org.apache.aries.jmx\:0.3=30
+#org.apache.aries.jmx\:org.apache.aries.jmx.blueprint\:0.3=30
+
+#org.apache.karaf.admin\:org.apache.karaf.admin.core\:${karaf.version}=30
+#org.apache.karaf.admin\:org.apache.karaf.admin.command\:${karaf.version}=30
+#org.apache.karaf.admin\:org.apache.karaf.admin.management\:${karaf.version}=30
+
+#org.apache.mina\:mina-core\:2.0.1=30
+#org.apache.sshd\:sshd-core\:0.5.0=30
+#org.apache.karaf.shell\:org.apache.karaf.shell.ssh\:${karaf.version}=30
+
+#org.apache.karaf.deployer\:org.apache.karaf.deployer.spring\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.blueprint\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.features\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.kar\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.wrap\:${karaf.version}=30
+
+# geronimo additions
+org.apache.felix\:org.apache.felix.scr\:1.6.0=15
+org.apache.felix\:org.apache.felix.shell\:1.5.0-SNAPSHOT=15
+org.apache.geronimo.bundles\:jaxb-impl\:2.2.3_1-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-stax-api_1.2_spec\:1.1-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-jaxb_2.2_spec\:1.0.2-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-activation_1.1_spec\:1.1=15
+org.apache.geronimo.bundles\:woodstox\:4.0.6_2-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-osgi-registry\:1.1-SNAPSHOT=15
+
+org.apache.geronimo.framework\:geronimo-kernel\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-crypto\:${geronimo.version}=40
+org.apache.felix\:org.apache.felix.bundlerepository\:${felix.bundlerepository.version}=40
+org.apache.xbean\:xbean-reflect\:${xbeanVersion}=40
+
+org.apache.geronimo.framework\:geronimo-system\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-common\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-pax-logging\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-main\:${geronimo.version}=40
+org.apache.servicemix.bundles\:org.apache.servicemix.bundles.commons-jexl\:1.1_3=40
+org.apache.xbean\:xbean-bundleutils\:${xbeanVersion}=40
\ No newline at end of file

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java Tue Apr 26 23:16:30 2011
@@ -0,0 +1,155 @@
+/*
+ * 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.geronimo.mavenplugins.car;
+
+import java.io.File;
+import java.lang.Override;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.sonatype.aether.RepositorySystem;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.resolution.ArtifactRequest;
+import org.sonatype.aether.resolution.ArtifactResolutionException;
+import org.sonatype.aether.resolution.ArtifactResult;
+import org.sonatype.aether.util.artifact.DefaultArtifact;
+
+/**
+ * Base for karaf-aware mojos
+ *
+ * @goal karaf-framework
+ * @requiresDependencyResolution runtime
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractFrameworkMojo extends AbstractMojo {
+    /**
+     * The entry point to Aether, i.e. the component doing all the work.
+     *
+     * @component
+     */
+    private RepositorySystem repoSystem;
+
+    /**
+     * The current repository/network configuration of Maven.
+     *
+     * @parameter default-value="${repositorySystemSession}"
+     * @readonly
+     */
+    private RepositorySystemSession repoSession;
+
+    /**
+     * The project's remote repositories to use for the resolution of plugins and their dependencies.
+     *
+     * @parameter default-value="${project.remoteProjectRepositories}"
+     * @readonly
+     */
+    private List<RemoteRepository> remoteRepos;
+
+    /**
+     * where we set up karaf
+     *
+     * @parameter default-value="${project.build.directory}/karaf"
+     */
+    private String karafHome;
+
+    private Framework framework;
+
+
+    @java.lang.Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        initializeFramework();
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+
+        }
+        ServiceReference sr = framework.getBundleContext().getServiceReference(FeaturesService.class.getName());
+        Object o = framework.getBundleContext().getService(sr);
+        if (o == null) {
+            throw new RuntimeException("no feature service found");
+        }
+        try {
+            framework.stop();
+        } catch (BundleException e) {
+            throw new MojoExecutionException("Can't stop framework: ", e );
+        }
+    }
+
+    void initializeFramework() throws MojoFailureException {
+        FrameworkHelper helper = new FrameworkHelper(karafHome, new AetherResolver(), Collections.<Artifact>emptyList());
+        try {
+            framework = helper.start();
+        } catch (Exception e) {
+            throw new MojoFailureException("Could not start karaf framework", e);
+        }
+    }
+
+    protected void listBundles() {
+        StringBuilder b = new StringBuilder("Bundles:");
+        for (Bundle bundle: framework.getBundleContext().getBundles()) {
+            b.append("\n   Id:").append(bundle.getBundleId()).append("  status:").append(bundle.getState()).append("  ").append(bundle.getLocation());
+        }
+        getLog().info(b.toString());
+    }
+
+    class AetherResolver implements FrameworkHelper.Resolver {
+
+        @Override
+        public File resolve(String id) {
+            if (id.startsWith("mvn:")) {
+                id = id.substring("mvn:".length()).replaceAll("/", ":");
+            }
+            ArtifactRequest request = new ArtifactRequest();
+            request.setArtifact(
+                    new DefaultArtifact(id));
+            request.setRepositories(remoteRepos);
+
+            getLog().debug("Resolving artifact " + id +
+                    " from " + remoteRepos);
+
+            ArtifactResult result;
+            try {
+                result = repoSystem.resolveArtifact(repoSession, request);
+            } catch (ArtifactResolutionException e) {
+                getLog().warn("could not resolve " + id, e);
+                return null;
+            }
+
+            getLog().debug("Resolved artifact " + id + " to " +
+                    result.getArtifact().getFile() + " from "
+                    + result.getRepository());
+            return result.getArtifact().getFile();
+        }
+    }
+
+
+}

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java Tue Apr 26 23:16:30 2011
@@ -0,0 +1,1488 @@
+/*
+ * 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.geronimo.mavenplugins.car;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.security.AccessControlException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+import java.util.ServiceLoader;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.main.BootstrapLogManager;
+import org.apache.karaf.main.Lock;
+import org.apache.karaf.main.ShutdownCallback;
+import org.apache.karaf.main.SimpleFileLock;
+import org.apache.karaf.main.StringMap;
+import org.apache.karaf.main.Utils;
+import org.apache.maven.artifact.Artifact;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * Mostly based on karaf Main class
+ *
+ * @version $Rev:$ $Date:$
+ */
+public class FrameworkHelper {
+
+    private String karafHomeString;
+    //path in karaf-framework kar containing etc dir.
+    //These have been copied into this plugin
+    private String etcLocation = "resources/etc/";
+
+    private Resolver resolver;
+
+    private List<Artifact> bundles;
+
+    public FrameworkHelper(String karafHome, Resolver resolver, List<Artifact> bundles) {
+        this.karafHomeString = karafHome;
+        File f = new File(karafHome);
+        if (f.exists() && !f.isDirectory()) {
+            throw new IllegalArgumentException("Karaf home exists but is not a directory: " + karafHome);
+        }
+        f.mkdirs();
+        this.resolver = resolver;
+        this.bundles = bundles;
+    }
+
+    public Framework start() throws Exception {
+        ThreadLocalProperties.install();
+        System.setProperty(PROP_KARAF_HOME, karafHomeString);
+        System.setProperty(PROP_KARAF_BASE, karafHomeString);
+        launch();
+        deployBundles(bundles);
+        return getFramework();
+    }
+
+    public void stop() throws Exception {
+        try {
+            destroy();
+        } finally {
+            ThreadLocalProperties.uninstall();
+        }
+    }
+
+    public void deployBundles(List<Artifact> bundles) throws BundleException {
+        BundleContext bundleContext = getFramework().getBundleContext();
+        List<Bundle> bundleIds = new ArrayList<Bundle>();
+        for (Artifact artifact: bundles) {
+            String location = artifact.getFile().getAbsolutePath();
+            bundleIds.add(bundleContext.installBundle(location));
+        }
+        for (Bundle bundle: bundleIds) {
+            bundle.start();
+        }
+    }
+
+    //modified copy of karaf Main class
+
+    /**
+     * The default name used for the system properties file.
+     */
+    public static final String SYSTEM_PROPERTIES_FILE_NAME = "system.properties";
+    /**
+     * The default name used for the configuration properties file.
+     */
+    public static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
+    /**
+     * The default name used for the startup properties file.
+     */
+    public static final String STARTUP_PROPERTIES_FILE_NAME = "startup.properties";
+    /**
+     * The property name prefix for the launcher's auto-install property.
+     */
+    public static final String PROPERTY_AUTO_INSTALL = "karaf.auto.install";
+    /**
+     * The property for auto-discovering the bundles
+     */
+    public static final String PROPERTY_AUTO_START = "karaf.auto.start";
+    /**
+     * The system property for specifying the Karaf home directory.  The home directory
+     * hold the binary install of Karaf.
+     */
+    public static final String PROP_KARAF_HOME = "karaf.home";
+    /**
+     * The environment variable for specifying the Karaf home directory.  The home directory
+     * hold the binary install of Karaf.
+     */
+    public static final String ENV_KARAF_HOME = "KARAF_HOME";
+    /**
+     * The system property for specifying the Karaf base directory.  The base directory
+     * holds the configuration and data for a Karaf instance.
+     */
+    public static final String PROP_KARAF_BASE = "karaf.base";
+    /**
+     * The environment variable for specifying the Karaf base directory.  The base directory
+     * holds the configuration and data for a Karaf instance.
+     */
+    public static final String ENV_KARAF_BASE = "KARAF_BASE";
+    /**
+     * The system property for specifying the Karaf data directory. The data directory
+     * holds the bundles data and cache for a Karaf instance.
+     */
+    public static final String PROP_KARAF_DATA = "karaf.data";
+    /**
+     * The environment variable for specifying the Karaf data directory. The data directory
+     * holds the bundles data and cache for a Karaf instance.
+     */
+    public static final String ENV_KARAF_DATA = "KARAF_DATA";
+    /**
+     * The system property for specifying the Karaf data directory. The data directory
+     * holds the bundles data and cache for a Karaf instance.
+     */
+    public static final String PROP_KARAF_INSTANCES = "karaf.instances";
+    /**
+     * The system property for specifying the Karaf data directory. The data directory
+     * holds the bundles data and cache for a Karaf instance.
+     */
+    public static final String ENV_KARAF_INSTANCES = "KARAF_INSTANCES";
+
+    /**
+     * Config property which identifies directories which contain bundles to be loaded by SMX
+     */
+    public static final String BUNDLE_LOCATIONS = "bundle.locations";
+
+    /**
+     * Config property that indicates we want to convert bundles locations to maven style urls
+     */
+    public static final String PROPERTY_CONVERT_TO_MAVEN_URL = "karaf.maven.convert";
+
+    /**
+     * If a lock should be used before starting the runtime
+     */
+    public static final String PROPERTY_USE_LOCK = "karaf.lock";
+
+    /**
+     * The lock implementation
+     */
+    public static final String PROPERTY_LOCK_CLASS = "karaf.lock.class";
+
+    public static final String PROPERTY_LOCK_DELAY = "karaf.lock.delay";
+
+    public static final String PROPERTY_LOCK_LEVEL = "karaf.lock.level";
+
+    public static final String DEFAULT_REPO = "karaf.default.repository";
+
+    public static final String KARAF_FRAMEWORK = "karaf.framework";
+
+    public static final String KARAF_FRAMEWORK_FACTORY = "karaf.framework.factory";
+
+    public static final String KARAF_SHUTDOWN_TIMEOUT = "karaf.shutdown.timeout";
+
+    public static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
+
+    public static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
+
+    public static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
+
+    public static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
+
+    public static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file";
+
+    public static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
+
+    public static final String PROPERTY_LOCK_CLASS_DEFAULT = SimpleFileLock.class.getName();
+
+    public static final String INCLUDES_PROPERTY = "${includes}";
+
+    Logger LOG = Logger.getLogger(this.getClass().getName());
+
+    private File karafHome;
+    private File karafBase;
+    private File karafData;
+    private File karafInstances;
+    private Properties configProps = null;
+    private Framework framework = null;
+    private int exitCode;
+    private Lock lock;
+    private int defaultStartLevel = 100;
+    private int lockStartLevel = 1;
+    private int lockDelay = 1000;
+    private int shutdownTimeout = 5 * 60 * 1000;
+    private boolean exiting = false;
+    private ShutdownCallback shutdownCallback;
+
+    public void setShutdownCallback(ShutdownCallback shutdownCallback) {
+        this.shutdownCallback = shutdownCallback;
+    }
+
+    public void launch() throws Exception {
+        karafHome = Utils.getKarafHome();
+        karafBase = Utils.getKarafDirectory(PROP_KARAF_BASE, ENV_KARAF_BASE, karafHome, false, true);
+        karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+        karafInstances = Utils.getKarafDirectory(PROP_KARAF_INSTANCES, ENV_KARAF_INSTANCES, new File(karafHome, "instances"), false, false);
+
+        //System.out.println("Karaf Home: "+main.karafHome.getPath());
+        //System.out.println("Karaf Base: "+main.karafBase.getPath());
+        //System.out.println("Karaf Data: "+main.karafData.getPath());
+
+        System.setProperty(PROP_KARAF_HOME, karafHome.getPath());
+        System.setProperty(PROP_KARAF_BASE, karafBase.getPath());
+        System.setProperty(PROP_KARAF_DATA, karafData.getPath());
+        System.setProperty(PROP_KARAF_INSTANCES, karafInstances.getPath());
+
+        // Load system properties.
+        loadSystemProperties(karafBase);
+
+        updateInstancePid();
+
+        // Read configuration properties.
+        configProps = loadConfigProperties();
+        BootstrapLogManager.setProperties(configProps);
+        LOG.addHandler(BootstrapLogManager.getDefaultHandler());
+
+        // Copy framework properties from the system properties.
+        copySystemProperties(configProps);
+
+        ClassLoader classLoader = createClassLoader(configProps);
+
+        processSecurityProperties(configProps);
+
+        if (configProps.getProperty(Constants.FRAMEWORK_STORAGE) == null) {
+            File storage = new File(karafData.getPath(), "cache");
+            try {
+                storage.mkdirs();
+            } catch (SecurityException se) {
+                throw new Exception(se.getMessage());
+            }
+            configProps.setProperty(Constants.FRAMEWORK_STORAGE, storage.getAbsolutePath());
+        }
+
+        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));
+        shutdownTimeout = Integer.parseInt(configProps.getProperty(KARAF_SHUTDOWN_TIMEOUT, Integer.toString(shutdownTimeout)));
+        // Start up the OSGI framework
+
+        String factoryClass = configProps.getProperty(KARAF_FRAMEWORK_FACTORY);
+        FrameworkFactory factory;
+        if (factoryClass == null) {
+            ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
+            factory = loader.iterator().next();
+        } else {
+            factory = (FrameworkFactory) classLoader.loadClass(factoryClass).newInstance();
+        }
+        framework = factory.newFramework(new StringMap(configProps, false));
+        framework.start();
+        processAutoProperties(framework.getBundleContext());
+        // Start lock monitor
+        new Thread() {
+            public void run() {
+                lock(configProps);
+            }
+        }.start();
+    }
+
+    public void awaitShutdown() throws Exception {
+        while (true) {
+            FrameworkEvent event = framework.waitForStop(0);
+            if (event.getType() != FrameworkEvent.STOPPED_UPDATE) {
+                return;
+            }
+        }
+    }
+
+	public boolean destroy() throws Exception {
+        if (framework == null) {
+            return true;
+        }
+        try {
+            int step = 5000;
+
+            // Notify the callback asap
+            if (shutdownCallback != null) {
+                shutdownCallback.waitingForShutdown(step);
+            }
+
+            // Stop the framework in case it's still active
+            exiting = true;
+            if (framework.getState() == Bundle.ACTIVE) {
+                new Thread() {
+                    public void run() {
+                        try {
+                            framework.stop();
+                        } catch (BundleException e) {
+                            System.err.println("Error stopping karaf: " + e.getMessage());
+                        }
+                    }
+                }.start();
+            }
+
+            int timeout = shutdownTimeout;
+            if (shutdownTimeout <= 0) {
+                timeout = Integer.MAX_VALUE;
+            }
+            while (timeout > 0) {
+                timeout -= step;
+                if (shutdownCallback != null) {
+                    shutdownCallback.waitingForShutdown(step * 2);
+                }
+                FrameworkEvent event = framework.waitForStop(step);
+                if (event.getType() != FrameworkEvent.WAIT_TIMEDOUT) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            unlock();
+        }
+    }
+
+    /**
+     * <p>
+     * This method performs the main task of constructing an framework instance
+     * and starting its execution. The following functions are performed
+     * when invoked:
+     * </p>
+     * <ol>
+     *   <li><i><b>Read the system properties file.<b></i> This is a file
+     *       containing properties to be pushed into <tt>System.setProperty()</tt>
+     *       before starting the framework. This mechanism is mainly shorthand
+     *       for people starting the framework from the command line to avoid having
+     *       to specify a bunch of <tt>-D</tt> system property definitions.
+     *       The only properties defined in this file that will impact the framework's
+     *       behavior are the those concerning setting HTTP proxies, such as
+     *       <tt>http.proxyHost</tt>, <tt>http.proxyPort</tt>, and
+     *       <tt>http.proxyAuth</tt>.
+     *   </li>
+     *   <li><i><b>Perform system property variable substitution on system
+     *       properties.</b></i> Any system properties in the system property
+     *       file whose value adheres to <tt>${&lt;system-prop-name&gt;}</tt>
+     *       syntax will have their value substituted with the appropriate
+     *       system property value.
+     *   </li>
+     *   <li><i><b>Read the framework's configuration property file.</b></i> This is
+     *       a file containing properties used to configure the framework
+     *       instance and to pass configuration information into
+     *       bundles installed into the framework instance. The configuration
+     *       property file is called <tt>config.properties</tt> by default
+     *       and is located in the <tt>conf/</tt> directory of the Felix
+     *       installation directory, which is the parent directory of the
+     *       directory containing the <tt>felix.jar</tt> file. It is possible
+     *       to use a different location for the property file by specifying
+     *       the desired URL using the <tt>felix.config.properties</tt>
+     *       system property; this should be set using the <tt>-D</tt> syntax
+     *       when executing the JVM. Refer to the
+     *       <a href="Felix.html#Felix(java.util.Map, java.util.List)">
+     *       <tt>Felix</tt></a> constructor documentation for more
+     *       information on the framework configuration options.
+     *   </li>
+     *   <li><i><b>Perform system property variable substitution on configuration
+     *       properties.</b></i> Any configuration properties whose value adheres to
+     *       <tt>${&lt;system-prop-name&gt;}</tt> syntax will have their value
+     *       substituted with the appropriate system property value.
+     *   </li>
+     *   <li><i><b>Ensure the default bundle cache has sufficient information to
+     *       initialize.</b></i> The default implementation of the bundle cache
+     *       requires either a profile name or a profile directory in order to
+     *       start. The configuration properties are checked for at least one
+     *       of the <tt>felix.cache.profile</tt> or <tt>felix.cache.profiledir</tt>
+     *       properties. If neither is found, the user is asked to supply a profile
+     *       name that is added to the configuration property set. See the
+     *       <a href="cache/DefaultBundleCache.html"><tt>DefaultBundleCache</tt></a>
+     *       documentation for more details its configuration options.
+     *   </li>
+     *   <li><i><b>Creates and starts a framework instance.</b></i> A
+     *       case insensitive
+     *       <a href="util/StringMap.html"><tt>StringMap</tt></a>
+     *       is created for the configuration property file and is passed
+     *       into the framework.
+     *   </li>
+     * </ol>
+     * <p>
+     * It should be noted that simply starting an instance of the framework is not enough
+     * to create an interactive session with it. It is necessary to install
+     * and start bundles that provide an interactive impl; this is generally
+     * done by specifying an "auto-start" property in the framework configuration
+     * property file. If no interactive impl bundles are installed or if
+     * the configuration property file cannot be found, the framework will appear to
+     * be hung or deadlocked. This is not the case, it is executing correctly,
+     * there is just no way to interact with it. Refer to the
+     * <a href="Felix.html#Felix(java.util.Map, java.util.List)">
+     * <tt>Felix</tt></a> constructor documentation for more information on
+     * framework configuration options.
+     * </p>
+//     * @param args An array of arguments, all of which are ignored.
+//     * @throws Exception If an error occurs.
+     **/
+//    public static void main(String[] args) throws Exception {
+//        while (true) {
+//            boolean restart = false;
+//            System.setProperty("karaf.restart", "false");
+//            if (Boolean.getBoolean("karaf.restart.clean")) {
+//                File karafHome = Utils.getKarafHome();
+//                File karafBase = Utils.getKarafDirectory(PROP_KARAF_BASE, ENV_KARAF_BASE, karafHome, false, true);
+//                File karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+//                Utils.deleteDirectory(karafData);
+//            }
+//            final Main main = new Main(args);
+//            try {
+//                main.launch();
+//            } catch (Throwable ex) {
+//                main.setExitCode(-1);
+//                System.err.println("Could not create framework: " + ex);
+//                ex.printStackTrace();
+//            }
+//            try {
+//                main.awaitShutdown();
+//                boolean stopped = main.destroy();
+//                restart = Boolean.getBoolean("karaf.restart");
+//                if (!stopped) {
+//                    if (restart) {
+//                        System.err.println("Timeout waiting for framework to stop.  Restarting now.");
+//                    } else {
+//                        System.err.println("Timeout waiting for framework to stop.  Exiting VM.");
+//                        main.setExitCode(-3);
+//                    }
+//                }
+//            } catch (Throwable ex) {
+//                main.setExitCode(-2);
+//                System.err.println("Error occured shutting down framework: " + ex);
+//                ex.printStackTrace();
+//            } finally {
+//                if (!restart) {
+//                    System.exit(main.getExitCode());
+//                }
+//            }
+//        }
+//    }
+
+    private static void processSecurityProperties(Properties m_configProps) {
+        String prop = m_configProps.getProperty("org.apache.karaf.security.providers");
+        if (prop != null) {
+            String[] providers = prop.split(",");
+            for (String provider : providers) {
+                addProvider(provider);
+            }
+        }
+    }
+
+    private static void addProvider(String provider) {
+        try {
+            Security.addProvider((Provider) Class.forName(provider).newInstance());
+        } catch (Throwable t) {
+            System.err.println("Unable to register security provider: " + t);
+        }
+    }
+
+    private void updateInstancePid() {
+        try {
+            String instanceName = System.getProperty("karaf.name");
+            String pid = ManagementFactory.getRuntimeMXBean().getName();
+            if (pid.indexOf('@') > 0) {
+                pid = pid.substring(0, pid.indexOf('@'));
+            }
+
+            boolean isRoot = karafHome.equals(karafBase);
+
+            if (instanceName != null) {
+                String storage = System.getProperty("karaf.instances");
+                if (storage == null) {
+                    throw new Exception("System property 'karaf.instances' is not set. \n" +
+                        "This property needs to be set to the full path of the instance.properties file.");
+                }
+                File storageFile = new File(storage);
+                File propertiesFile = new File(storageFile, "instance.properties");
+                Properties props = new Properties();
+                if (propertiesFile.exists()) {
+                    FileInputStream fis = new FileInputStream(propertiesFile);
+                    props.load(fis);
+                    int count = Integer.parseInt(props.getProperty("count"));
+                    for (int i = 0; i < count; i++) {
+                        String name = props.getProperty("item." + i + ".name");
+                        if (name.equals(instanceName)) {
+                            props.setProperty("item." + i + ".pid", pid);
+                            FileOutputStream fos = new FileOutputStream(propertiesFile);
+                            props.store(fos, null);
+                            fis.close();
+                            fos.close();
+                            return;
+                        }
+                    }
+                    fis.close();
+                    if (!isRoot) {
+                        throw new Exception("Instance " + instanceName + " not found");
+                    }
+                } else if (isRoot) {
+                    if (!propertiesFile.getParentFile().exists()) {
+                        try {
+                            propertiesFile.getParentFile().mkdirs();
+                        } catch (SecurityException se) {
+                            throw new Exception(se.getMessage());
+                        }
+                    }
+                    props.setProperty("count", "1");
+                    props.setProperty("item.0.name", instanceName);
+                    props.setProperty("item.0.loc", karafHome.getAbsolutePath());
+                    props.setProperty("item.0.pid", pid);
+                    props.setProperty("item.0.root", "true");
+                    FileOutputStream fos = new FileOutputStream(propertiesFile);
+                    props.store(fos, null);
+                    fos.close();
+                }
+            }
+        } catch (Exception e) {
+            System.err.println("Unable to update instance pid: " + e.getMessage());
+        }
+    }
+
+    /**
+     * <p/>
+     * Processes the auto-install and auto-start properties from the
+     * specified configuration properties.
+     *
+     * @param context the system bundle context
+     */
+    private void processAutoProperties(BundleContext context) {
+        // Check if we want to convert URLs to maven style
+        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.
+        StartLevel sl = (StartLevel) context.getService(
+                context.getServiceReference(org.osgi.service.startlevel.StartLevel.class.getName()));
+
+        // Set the default bundle start level
+        int ibsl = 60;
+        try {
+            String str = configProps.getProperty("karaf.startlevel.bundle");
+            if (str != null) {
+                ibsl = Integer.parseInt(str);
+            }
+        } catch (Throwable t) {
+        }
+        sl.setInitialBundleStartLevel(ibsl);
+
+        // The auto-install property specifies a space-delimited list of
+        // bundle URLs to be automatically installed into each new profile;
+        // 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.
+        autoInstall(PROPERTY_AUTO_INSTALL, context, sl, convertToMavenUrls, false);
+
+        // The auto-start property specifies a space-delimited list of
+        // bundle URLs to be automatically installed and started into each
+        // new profile; the start level to which the bundles are assigned
+        // is specified by appending a ".n" to the auto-start property name,
+        // where "n" is the desired start level for the list of bundles.
+        // The following code starts bundles in one pass, installing bundles
+        // for a given level, then starting them, then moving to the next level.
+        autoInstall(PROPERTY_AUTO_START, context, sl, convertToMavenUrls, true);
+    }
+
+    private List<Bundle> autoInstall(String propertyPrefix, BundleContext context, StartLevel sl, boolean convertToMavenUrls, boolean start) {
+        Map<Integer, String> autoStart = new TreeMap<Integer, String>();
+        List<Bundle> bundles = new ArrayList<Bundle>();
+        for (Object o : configProps.keySet()) {
+            String key = (String) o;
+            // Ignore all keys that are not the auto-start property.
+            if (!key.startsWith(propertyPrefix)) {
+                continue;
+            }
+            // If the auto-start property does not have a start level,
+            // then assume it is the default bundle start level, otherwise
+            // parse the specified start level.
+            int startLevel = sl.getInitialBundleStartLevel();
+            if (!key.equals(propertyPrefix)) {
+                try {
+                    startLevel = Integer.parseInt(key.substring(key.lastIndexOf('.') + 1));
+                } catch (NumberFormatException ex) {
+                    System.err.println("Invalid property: " + key);
+                }
+            }
+            autoStart.put(startLevel, configProps.getProperty(key));
+        }
+        for (Integer startLevel : autoStart.keySet()) {
+            StringTokenizer st = new StringTokenizer(autoStart.get(startLevel), "\" ", true);
+            if (st.countTokens() > 0) {
+                String location;
+                do {
+                    location = nextLocation(st);
+                    if (location != null) {
+                        try {
+                            String[] parts = convertToMavenUrlsIfNeeded(location, convertToMavenUrls);
+                            Bundle b = context.installBundle(parts[0], new URL(parts[1]).openStream());
+                            sl.setBundleStartLevel(b, startLevel);
+                            bundles.add(b);
+                        }
+                        catch (Exception ex) {
+                            System.err.println("Error installing bundle  " + location + ": " + ex);
+                        }
+                    }
+                }
+                while (location != null);
+            }
+        }
+        // Now loop through and start the installed bundles.
+        if (start) {
+            for (Bundle b : bundles) {
+                try {
+                    String fragmentHostHeader = (String) b.getHeaders().get(Constants.FRAGMENT_HOST);
+                    if (fragmentHostHeader == null || fragmentHostHeader.trim().length() == 0) {
+                        b.start();
+                    }
+                }
+                catch (Exception ex) {
+                    System.err.println("Error starting bundle " + b.getSymbolicName() + ": " + ex);
+                }
+            }
+        }
+        return bundles;
+    }
+
+    private static String[] convertToMavenUrlsIfNeeded(String location, boolean convertToMavenUrls) {
+        String[] parts = location.split("\\|");
+        if (convertToMavenUrls) {
+            String[] p = parts[1].split("/");
+            if (p.length >= 4 && p[p.length-1].startsWith(p[p.length-3] + "-" + p[p.length-2])) {
+                String artifactId = p[p.length-3];
+                String version = p[p.length-2];
+                String classifier;
+                String type;
+                String artifactIdVersion = artifactId + "-" + version;
+                StringBuffer sb = new StringBuffer();
+                if (p[p.length-1].charAt(artifactIdVersion.length()) == '-') {
+                    classifier = p[p.length-1].substring(artifactIdVersion.length() + 1, p[p.length-1].lastIndexOf('.'));
+                } else {
+                    classifier = null;
+                }
+                type = p[p.length-1].substring(p[p.length-1].lastIndexOf('.') + 1);
+                sb.append("mvn:");
+                for (int j = 0; j < p.length - 3; j++) {
+                    if (j > 0) {
+                        sb.append('.');
+                    }
+                    sb.append(p[j]);
+                }
+                sb.append('/').append(artifactId).append('/').append(version);
+                if (!"jar".equals(type) || classifier != null) {
+                    sb.append('/');
+                    if (!"jar".equals(type)) {
+                        sb.append(type);
+                    }
+                    if (classifier != null) {
+                        sb.append('/').append(classifier);
+                    }
+                }
+                parts[1] = parts[0];
+                parts[0] = sb.toString();
+            } else {
+                parts[1] = parts[0];
+            }
+        } else {
+            parts[1] = parts[0];
+        }
+        return parts;
+    }
+
+    private static String nextLocation(StringTokenizer st) {
+        String retVal = null;
+
+        if (st.countTokens() > 0) {
+            String tokenList = "\" ";
+            StringBuffer tokBuf = new StringBuffer(10);
+            String tok;
+            boolean inQuote = false;
+            boolean tokStarted = false;
+            boolean exit = false;
+            while ((st.hasMoreTokens()) && (!exit)) {
+                tok = st.nextToken(tokenList);
+                if (tok.equals("\"")) {
+                    inQuote = !inQuote;
+                    if (inQuote) {
+                        tokenList = "\"";
+                    } else {
+                        tokenList = "\" ";
+                    }
+
+                } else if (tok.equals(" ")) {
+                    if (tokStarted) {
+                        retVal = tokBuf.toString();
+                        tokStarted = false;
+                        tokBuf = new StringBuffer(10);
+                        exit = true;
+                    }
+                } else {
+                    tokStarted = true;
+                    tokBuf.append(tok.trim());
+                }
+            }
+
+            // Handle case where end of token stream and
+            // still got data
+            if ((!exit) && (tokStarted)) {
+                retVal = tokBuf.toString();
+            }
+        }
+
+        return retVal;
+    }
+
+    /**
+     * <p>
+     * Loads the properties in the system property file associated with the
+     * framework installation into <tt>System.setProperty()</tt>. These properties
+     * are not directly used by the framework in anyway. By default, the system
+     * property file is located in the <tt>conf/</tt> directory of the Felix
+     * installation directory and is called "<tt>system.properties</tt>". The
+     * installation directory of Felix is assumed to be the parent directory of
+     * the <tt>felix.jar</tt> file as found on the system class path property.
+     * The precise file from which to load system properties can be set by
+     * initializing the "<tt>felix.system.properties</tt>" system property to an
+     * arbitrary URL.
+     * </p>
+     *
+     * @param karafBase the karaf base folder
+     */
+    protected static void loadSystemProperties(File karafBase) {
+        // The system properties file is either specified by a system
+        // property or it is in the same directory as the Felix JAR file.
+        // Try to load it from one of these places.
+
+        // See if the property URL was specified as a property.
+        URL propURL;
+        try {
+            File file = new File(new File(karafBase, "etc"), SYSTEM_PROPERTIES_FILE_NAME);
+            propURL = file.toURI().toURL();
+        }
+        catch (MalformedURLException ex) {
+            System.err.print("Main: " + ex);
+            return;
+        }
+
+        // Read the properties file.
+        Properties props = new Properties();
+        InputStream is = null;
+        try {
+            is = propURL.openConnection().getInputStream();
+            props.load(is);
+            is.close();
+        }
+        catch (FileNotFoundException ex) {
+            // Ignore file not found.
+        }
+        catch (Exception ex) {
+            System.err.println(
+                    "Main: Error loading system properties from " + propURL);
+            System.err.println("Main: " + ex);
+            try {
+                if (is != null) is.close();
+            }
+            catch (IOException ex2) {
+                // Nothing we can do.
+            }
+            return;
+        }
+
+        // Perform variable substitution on specified properties.
+        for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            String value = System.getProperty(name, props.getProperty(name));
+            System.setProperty(name, substVars(value, name, null, null));
+        }
+    }
+
+    /**
+     * <p>
+     * Loads the configuration properties in the configuration property file
+     * associated with the framework installation; these properties
+     * are accessible to the framework and to bundles and are intended
+     * for configuration purposes. By default, the configuration property
+     * file is located in the <tt>conf/</tt> directory of the Felix
+     * installation directory and is called "<tt>config.properties</tt>".
+     * The installation directory of Felix is assumed to be the parent
+     * directory of the <tt>felix.jar</tt> file as found on the system class
+     * path property. The precise file from which to load configuration
+     * properties can be set by initializing the "<tt>felix.config.properties</tt>"
+     * system property to an arbitrary URL.
+     * </p>
+     *
+     * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
+     * @throws Exception if something wrong occurs
+     */
+    private Properties loadConfigProperties() throws Exception {
+        // The config properties file is either specified by a system
+        // property or it is in the conf/ directory of the Felix
+        // installation directory.  Try to load it from one of these
+        // places.
+
+        List<File> bundleDirs = new ArrayList<File>();
+
+        // See if the property URL was specified as a property.
+        URL configPropURL;
+        URL startupPropURL;
+
+//            File file = new File(new File(karafBase, "etc"), CONFIG_PROPERTIES_FILE_NAME);
+            configPropURL = getClass().getClassLoader().getResource(etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+
+//            file = new File(new File(karafBase, "etc"), STARTUP_PROPERTIES_FILE_NAME);
+            startupPropURL = getClass().getClassLoader().getResource(etcLocation + STARTUP_PROPERTIES_FILE_NAME);
+
+        if (configPropURL == null) {
+            System.err.println("Could not locate config.properties file in classpath at " + etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+            return null;
+        }
+        if (startupPropURL == null) {
+            System.err.println("Could not locate startup.properties file in classpath at " + etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+            return null;
+        }
+
+        Properties configProps = loadPropertiesFile(configPropURL, false);
+        Properties startupProps = loadPropertiesFile(startupPropURL, true);
+
+        String defaultRepo = System.getProperty(DEFAULT_REPO, "system");
+
+        if (karafBase.equals(karafHome)) {
+            bundleDirs.add(new File(karafHome, defaultRepo));
+        } else {
+            bundleDirs.add(new File(karafBase, defaultRepo));
+            bundleDirs.add(new File(karafHome, defaultRepo));
+        }
+
+        String locations = configProps.getProperty(BUNDLE_LOCATIONS);
+
+        if (locations != null) {
+            StringTokenizer st = new StringTokenizer(locations, "\" ", true);
+            if (st.countTokens() > 0) {
+                String location;
+                do {
+                    location = nextLocation(st);
+                    if (location != null) {
+                        File f;
+                        if (karafBase.equals(karafHome)) {
+                        	f = new File(karafHome, location);
+                        } else {
+                        	f = new File(karafBase, location);
+                        }
+                        if (f.exists() && f.isDirectory()) {
+                            bundleDirs.add(f);
+                        } else {
+                            System.err.println("Bundle location " + location
+                                    + " does not exist or is not a directory.");
+                        }
+                    }
+                }
+
+                while (location != null);
+            }
+        }
+
+        // Perform variable substitution for system properties.
+        for (Enumeration e = configProps.propertyNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            configProps.setProperty(name,
+                    substVars(configProps.getProperty(name), name, null, configProps));
+        }
+
+        // Mutate properties
+        processConfigurationProperties(configProps, startupProps, bundleDirs);
+
+        return configProps;
+    }
+
+    protected static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
+        // Read the properties file.
+        Properties configProps = new Properties();
+        InputStream is = null;
+        try {
+            is = configPropURL.openConnection().getInputStream();
+            configProps.load(is);
+            is.close();
+        }
+        catch (FileNotFoundException ex) {
+            if (failIfNotFound) {
+                throw ex;
+            }
+        }
+        catch (Exception ex) {
+            System.err.println("Error loading config properties from " + configPropURL);
+            System.err.println("Main: " + ex);
+            return configProps;
+        } finally {
+            try {
+                if (is != null) {
+                    is.close();
+                }
+            }
+            catch (IOException ex2) {
+                // Nothing we can do.
+            }
+        }
+        String includes = configProps.getProperty(INCLUDES_PROPERTY);
+        if (includes != null) {
+            StringTokenizer st = new StringTokenizer(includes, "\" ", true);
+            if (st.countTokens() > 0) {
+                String location;
+                do {
+                    location = nextLocation(st);
+                    if (location != null) {
+                        URL url = new URL(configPropURL, location);
+                        Properties props = loadPropertiesFile(url, true);
+                        configProps.putAll(props);
+                    }
+                }
+                while (location != null);
+            }
+            configProps.remove(INCLUDES_PROPERTY);
+        }
+        for (Enumeration e = configProps.propertyNames(); e.hasMoreElements();) {
+            Object key = e.nextElement();
+            if (key instanceof String) {
+                String v = configProps.getProperty((String) key);
+                configProps.put(key, v.trim());
+            }
+        }
+        return configProps;
+    }
+
+    protected static void copySystemProperties(Properties configProps) {
+        for (Enumeration e = System.getProperties().propertyNames();
+             e.hasMoreElements();) {
+            String key = (String) e.nextElement();
+            if (key.startsWith("felix.") ||
+                    key.startsWith("karaf.") ||
+                    key.startsWith("org.osgi.framework.")) {
+                configProps.setProperty(key, System.getProperty(key));
+            }
+        }
+    }
+
+    private ClassLoader createClassLoader(Properties configProps) throws Exception {
+        return getClass().getClassLoader();
+//    	String framework = configProps.getProperty(KARAF_FRAMEWORK);
+//        if (framework == null) {
+//            throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + " must be set in the etc/" + CONFIG_PROPERTIES_FILE_NAME + " configuration file");
+//        }
+//        String bundle = configProps.getProperty(KARAF_FRAMEWORK + "." + framework);
+//        if (bundle == null) {
+//            throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + "." + framework + " must be set in the etc/" + CONFIG_PROPERTIES_FILE_NAME + " configuration file");
+//        }
+//        File bundleFile = new File(karafBase, bundle);
+//        if (!bundleFile.exists()) {
+//            bundleFile = new File(karafHome, bundle);
+//        }
+//        if (!bundleFile.exists()) {
+//            throw new FileNotFoundException(bundleFile.getAbsolutePath());
+//        }
+//
+//        List<URL> urls = new ArrayList<URL>();
+//        urls.add( bundleFile.toURI().toURL() );
+//        File[] libs = new File(karafHome, "lib").listFiles();
+//        if (libs != null) {
+//            for (File f : libs) {
+//                if (f.isFile() && f.canRead() && f.getName().endsWith(".jar")) {
+//                    urls.add(f.toURI().toURL());
+//                }
+//            }
+//        }
+//
+//        return new URLClassLoader(urls.toArray(new URL[urls.size()]), Main.class.getClassLoader());
+    }
+
+    /**
+     * Process properties to customize default felix behavior
+     *
+     * @param configProps properties loaded from etc/config.properties
+     * @param startupProps properties loaded from etc/startup.properties
+     * @param bundleDirs location to load bundles from (usually system/)
+     */
+    private void processConfigurationProperties(Properties configProps, Properties startupProps, List<File> bundleDirs) {
+        if (bundleDirs == null) {
+            return;
+        }
+        if ("all".equals(configProps.getProperty(PROPERTY_AUTO_START, "").trim())) {
+            configProps.remove(PROPERTY_AUTO_START);
+            ArrayList<File> jars = new ArrayList<File>();
+
+            // We should start all the bundles in the system dir.
+            for (File bundleDir : bundleDirs) {
+                findJars(bundleDir, jars);
+            }
+
+            StringBuffer sb = new StringBuffer();
+
+            for (File jar : jars) {
+                try {
+                    sb.append("\"").append(jar.toURI().toURL().toString()).append("\" ");
+                } catch (MalformedURLException e) {
+                    System.err.print("Ignoring " + jar.toString() + " (" + e + ")");
+                }
+            }
+
+            configProps.setProperty(PROPERTY_AUTO_START, sb.toString());
+
+        } else if (STARTUP_PROPERTIES_FILE_NAME.equals(configProps.getProperty(PROPERTY_AUTO_START, "").trim())) {
+            configProps.remove(PROPERTY_AUTO_START);
+            // We should start the bundles in the startup.properties file.
+            HashMap<Integer, StringBuffer> levels = new HashMap<Integer, StringBuffer>();
+            for (Object o : startupProps.keySet()) {
+                String name = (String) o;
+                File file = resolver == null? findFile(bundleDirs, name): resolver.resolve(name);
+
+                if (file != null) {
+                    Integer level;
+                    try {
+                        level = new Integer(startupProps.getProperty(name).trim());
+                    } catch (NumberFormatException e1) {
+                        System.err.print("Ignoring " + file.toString() + " (run level must be an integer)");
+                        continue;
+                    }
+                    StringBuffer sb = levels.get(level);
+                    if (sb == null) {
+                        sb = new StringBuffer(256);
+                        levels.put(level, sb);
+                    }
+                    try {
+                        sb.append("\"").append(file.toURI().toURL().toString()).append("|").append(name).append("\" ");
+                    } catch (MalformedURLException e) {
+                        System.err.print("Ignoring " + file.toString() + " (" + e + ")");
+                    }
+                } else {
+                    System.err.println("Bundle listed in " + STARTUP_PROPERTIES_FILE_NAME + " configuration not found: " + name);
+                }
+            }
+
+            for (Map.Entry<Integer, StringBuffer> entry : levels.entrySet()) {
+                configProps.setProperty(PROPERTY_AUTO_START + "." + entry.getKey(), entry.getValue().toString());
+            }
+        }
+
+    }
+
+    private static File findFile(List<File> bundleDirs, String name) {
+        for (File bundleDir : bundleDirs) {
+            File file = findFile(bundleDir, name);
+            if (file != null) {
+                return file;
+            }
+        }
+        return null;
+    }
+
+    private static File findFile(File dir, String name) {
+        name = fromMaven(name);
+        File theFile = new File(dir, name);
+
+        if (theFile.exists() && !theFile.isDirectory()) {
+            return theFile;
+        }
+        return null;
+    }
+
+    /**
+     * Returns a path for an srtifact.
+     * Input: path (no ':') returns path
+     * Input: mvn:<groupId>/<artifactId>/<version>/<type>/<classifier> converts to default repo location path
+     * Input:  <groupId>:<artifactId>:<version>:<type>:<classifier> converts to default repo location path
+     * type and classifier are optional.
+     *
+     *
+     * @param name input artifact info
+     * @return path as supplied or a default maven repo path
+     */
+    private static String fromMaven(String name) {
+        if (name.indexOf(':') == -1) {
+            return name;
+        }
+        int firstBit = 0;
+        if (name.startsWith("mvn:")) {
+            firstBit = 1;
+        }
+        String[] bits = name.split("[:/]");
+        StringBuilder b = new StringBuilder(bits[firstBit]);
+        for (int i = 0; i < b.length(); i++) {
+            if (b.charAt(i) == '.') {
+                b.setCharAt(i, '/');
+            }
+        }
+        b.append('/').append(bits[firstBit + 1]); //artifactId
+        b.append('/').append(bits[firstBit + 2]); //version
+        b.append('/').append(bits[firstBit + 1]).append('-').append(bits[firstBit + 2]);
+        if (bits.length == firstBit + 5 && !bits[firstBit + 4].isEmpty()) {
+            b.append('-').append(bits[firstBit + 4]); //classifier
+        }
+        if (bits.length >= firstBit + 4 && !bits[firstBit + 3].isEmpty()) {
+            b.append('.').append(bits[firstBit + 3]);
+        } else {
+            b.append(".jar");
+        }
+        return b.toString();
+    }
+
+    private static void findJars(File dir, ArrayList<File> jars) {
+        for (File file : dir.listFiles()) {
+            if (file.isDirectory()) {
+                findJars(file, jars);
+            } else {
+                if (file.toString().endsWith(".jar")) {
+                    jars.add(file);
+                }
+            }
+        }
+    }
+
+    private static final String DELIM_START = "${";
+    private static final String DELIM_STOP = "}";
+
+    /**
+     * <p>
+     * This method performs property variable substitution on the
+     * specified value. If the specified value contains the syntax
+     * <tt>${&lt;prop-name&gt;}</tt>, where <tt>&lt;prop-name&gt;</tt>
+     * refers to either a configuration property or a system property,
+     * then the corresponding property value is substituted for the variable
+     * placeholder. Multiple variable placeholders may exist in the
+     * specified value as well as nested variable placeholders, which
+     * are substituted from inner most to outer most. Configuration
+     * properties override system properties.
+     * </p>
+     *
+     * @param val         The string on which to perform property substitution.
+     * @param currentKey  The key of the property being evaluated used to
+     *                    detect cycles.
+     * @param cycleMap    Map of variable references used to detect nested cycles.
+     * @param configProps Set of configuration properties.
+     * @return The value of the specified string after system property substitution.
+     * @throws IllegalArgumentException If there was a syntax error in the
+     *                                  property placeholder syntax or a recursive variable reference.
+     */
+    public static String substVars(String val, String currentKey,
+                                    Map<String, String> cycleMap, Properties configProps)
+            throws IllegalArgumentException {
+        // If there is currently no cycle map, then create
+        // one for detecting cycles for this invocation.
+        if (cycleMap == null) {
+            cycleMap = new HashMap<String, String>();
+        }
+
+        // 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"
+
+        // Find the first ending '}' variable delimiter, which
+        // will correspond to the first deepest nested variable
+        // placeholder.
+        int stopDelim = val.indexOf(DELIM_STOP);
+
+        // Find the matching starting "${" variable delimiter
+        // by looping until we find a start delimiter that is
+        // greater than the stop delimiter we have found.
+        int startDelim = val.indexOf(DELIM_START);
+        while (stopDelim >= 0) {
+            int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
+            if ((idx < 0) || (idx > stopDelim)) {
+                break;
+            } else if (idx < stopDelim) {
+                startDelim = idx;
+            }
+        }
+
+        // If we do not have a start or stop delimiter, then just
+        // return the existing value.
+        if ((startDelim < 0) && (stopDelim < 0)) {
+            return val;
+        }
+        // At this point, we found a stop delimiter without a start,
+        // so throw an exception.
+        else if (((startDelim < 0) || (startDelim > stopDelim))
+                && (stopDelim >= 0)) {
+            throw new IllegalArgumentException(
+                    "stop delimiter with no start delimiter: "
+                            + val);
+        }
+
+        // At this point, we have found a variable placeholder so
+        // we must perform a variable substitution on it.
+        // Using the start and stop delimiter indices, extract
+        // the first, deepest nested variable placeholder.
+        String variable =
+                val.substring(startDelim + DELIM_START.length(), stopDelim);
+
+        // Verify that this is not a recursive variable reference.
+        if (cycleMap.get(variable) != null) {
+            throw new IllegalArgumentException(
+                    "recursive variable reference: " + variable);
+        }
+
+        // Get the value of the deepest nested variable placeholder.
+        // Try to configuration properties first.
+        String substValue = (configProps != null)
+                ? configProps.getProperty(variable, null)
+                : null;
+        if (substValue == null) {
+            // Ignore unknown property values.
+            substValue = System.getProperty(variable, "");
+        }
+
+        // Remove the found variable from the cycle map, since
+        // it may appear more than once in the value and we don't
+        // want such situations to appear as a recursive reference.
+        cycleMap.remove(variable);
+
+        // Append the leading characters, the substituted value of
+        // the variable, and the trailing characters to get the new
+        // value.
+        val = val.substring(0, startDelim)
+                + substValue
+                + val.substring(stopDelim + DELIM_STOP.length(), val.length());
+
+        // Now perform substitution again, since there could still
+        // be substitutions to make.
+        val = substVars(val, currentKey, cycleMap, configProps);
+
+        // Return the value.
+        return val;
+    }
+
+    public Framework getFramework() {
+        return framework;
+    }
+
+    public void lock(Properties props) {
+        try {
+            if (Boolean.parseBoolean(props.getProperty(PROPERTY_USE_LOCK, "true"))) {
+                doLock(props);
+            } else {
+                setStartLevel(defaultStartLevel);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void doLock(Properties props) throws Exception {
+        String clz = props.getProperty(PROPERTY_LOCK_CLASS, PROPERTY_LOCK_CLASS_DEFAULT);
+        lock = (Lock) Class.forName(clz).getConstructor(Properties.class).newInstance(props);
+        boolean lockLogged = false;
+        setStartLevel(lockStartLevel);
+        while (!exiting) {
+            if (lock.lock()) {
+                if (lockLogged) {
+                    LOG.info("Lock acquired.");
+                }
+                setupShutdown(props);
+                setStartLevel(defaultStartLevel);
+                for (;;) {
+                    if (!lock.isAlive()) {
+                        break;
+                    }
+                    Thread.sleep(lockDelay);
+                }
+                if (framework.getState() == Bundle.ACTIVE && !exiting) {
+                    LOG.info("Lost the lock, stopping this instance ...");
+                    setStartLevel(lockStartLevel);
+                }
+            } else if (!lockLogged) {
+                LOG.info("Waiting for the lock ...");
+                lockLogged = true;
+            }
+            Thread.sleep(lockDelay);
+        }
+    }
+
+    public void unlock() throws Exception {
+        if (lock != null) {
+            lock.release();
+        }
+    }
+
+    protected void setStartLevel(int level) throws Exception {
+        BundleContext ctx = framework.getBundleContext();
+        ServiceReference[] refs = ctx.getServiceReferences(StartLevel.class.getName(), null);
+        StartLevel sl = (StartLevel) ctx.getService(refs[0]);
+        sl.setStartLevel(level);
+    }
+
+
+    private Random random = null;
+    private ServerSocket shutdownSocket;
+
+    protected void setupShutdown(Properties props) {
+        writePid(props);
+        try {
+            int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
+            String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
+            String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
+            final String shutdown = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
+            if (port >= 0) {
+                shutdownSocket = new ServerSocket(port, 1, InetAddress.getByName(host));
+                if (port == 0) {
+                    port = shutdownSocket.getLocalPort();
+                }
+                if (portFile != null) {
+                    Writer w = new OutputStreamWriter(new FileOutputStream(portFile));
+                    w.write(Integer.toString(port));
+                    w.close();
+                }
+                Thread thread = new ShutdownSocketThread(shutdown);
+                thread.setDaemon(true);
+                thread.start();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void writePid(Properties props) {
+        try {
+            String pidFile = props.getProperty(KARAF_SHUTDOWN_PID_FILE);
+            if (pidFile != null) {
+                RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
+                String processName = rtb.getName();
+                Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE);
+                Matcher matcher = pattern.matcher(processName);
+                if (matcher.matches()) {
+                    int pid = Integer.parseInt(matcher.group(1));
+                    Writer w = new OutputStreamWriter(new FileOutputStream(pidFile));
+                    w.write(Integer.toString(pid));
+                    w.close();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private class ShutdownSocketThread extends Thread {
+
+        private final String shutdown;
+
+        public ShutdownSocketThread(String shutdown) {
+            this.shutdown = shutdown;
+        }
+
+        public void run() {
+            try {
+                while (true) {
+                    // Wait for the next connection
+                    Socket socket = null;
+                    InputStream stream = null;
+                    try {
+                        socket = shutdownSocket.accept();
+                        socket.setSoTimeout(10 * 1000);  // Ten seconds
+                        stream = socket.getInputStream();
+                    } catch (AccessControlException ace) {
+                        LOG.log(Level.WARNING, "Karaf shutdown socket: security exception: "
+                                           + ace.getMessage(), ace);
+                        continue;
+                    } catch (IOException e) {
+                        LOG.log(Level.SEVERE, "Karaf shutdown socket: accept: ", e);
+                        System.exit(1);
+                    }
+
+                    // Read a set of characters from the socket
+                    StringBuilder command = new StringBuilder();
+                    int expected = 1024; // Cut off to avoid DoS attack
+                    while (expected < shutdown.length()) {
+                        if (random == null) {
+                            random = new Random();
+                        }
+                        expected += (random.nextInt() % 1024);
+                    }
+                    while (expected > 0) {
+                        int ch;
+                        try {
+                            ch = stream.read();
+                        } catch (IOException e) {
+                            LOG.log(Level.WARNING, "Karaf shutdown socket:  read: ", e);
+                            ch = -1;
+                        }
+                        if (ch < 32) {  // Control character or EOF terminates loop
+                            break;
+                        }
+                        command.append((char) ch);
+                        expected--;
+                    }
+
+                    // Close the socket now that we are done with it
+                    try {
+                        socket.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+
+                    // Match against our command string
+                    boolean match = command.toString().equals(shutdown);
+                    if (match) {
+                        LOG.log(Level.INFO, "Karaf shutdown socket: received shutdown command. Stopping framework...");
+                        framework.stop();
+                        break;
+                    } else {
+                        LOG.log(Level.WARNING, "Karaf shutdown socket:  Invalid command '" +
+                                           command.toString() + "' received");
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    shutdownSocket.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+    }
+
+    public interface Resolver {
+        File resolve(String id);
+    }
+
+}

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain