You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2012/05/06 17:50:05 UTC

svn commit: r1334671 [1/2] - in /karaf/trunk: assemblies/features/framework/src/main/filtered-resources/resources/etc/ assemblies/features/framework/src/main/resources/resources/etc/ itests/tests/src/test/resources/org/apache/karaf/testing/ main/src/ma...

Author: cschneider
Date: Sun May  6 15:50:04 2012
New Revision: 1334671

URL: http://svn.apache.org/viewvc?rev=1334671&view=rev
Log:
KARAF-1296 First step. Using only startup.properties

Added:
    karaf/trunk/main/src/main/java/org/apache/karaf/main/ConfigProperties.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/ServerInfoImpl.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockCallBack.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/util/ArtifactResolver.java
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/aries/
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/aries/blueprint/
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/0.3.1/
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/0.3.1/org.apache.aries.blueprint.api-0.3.1.jar   (with props)
    karaf/trunk/main/src/test/resources/test-karaf-home/system/pax-url-mvn.jar
      - copied unchanged from r1334416, karaf/trunk/main/src/test/resources/test-karaf-home/bundles/pax-url-mvn.jar
Removed:
    karaf/trunk/main/src/test/resources/test-karaf-home/bundles/
    karaf/trunk/main/src/test/resources/test-karaf-home/system/org/apache/felix/org.apache.felix.framework/3.0.6/
Modified:
    karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
    karaf/trunk/assemblies/features/framework/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
    karaf/trunk/itests/tests/src/test/resources/org/apache/karaf/testing/startup.properties
    karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/PropertiesLoader.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/Stop.java
    karaf/trunk/main/src/main/java/org/apache/karaf/main/util/SimpleMavenResolver.java
    karaf/trunk/main/src/test/java/org/apache/karaf/main/MainStartTest.java
    karaf/trunk/main/src/test/resources/test-karaf-home/etc/config.properties
    karaf/trunk/main/src/test/resources/test-karaf-home/etc/startup.properties

Modified: karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
URL: http://svn.apache.org/viewvc/karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties (original)
+++ karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties Sun May  6 15:50:04 2012
@@ -50,8 +50,8 @@ karaf.framework=felix
 #
 # Location of the OSGi frameworks
 #
-karaf.framework.equinox=${karaf.default.repository}/org/eclipse/osgi/${equinox.version}/osgi-${equinox.version}.jar
-karaf.framework.felix=${karaf.default.repository}/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar
+karaf.framework.equinox=mvn\:org.eclipse/osgi/3.7.1.R37x_v20110808-1106
+karaf.framework.felix=mvn\:org.apache.felix/org.apache.felix.framework/4.0.2
 
 #
 # Framework config properties.
@@ -86,9 +86,6 @@ org.osgi.framework.executionenvironment=
 # Set the parent classloader for the bundle to the classloader that loads the Framework (i.e. everything in lib/*.jar)
 org.osgi.framework.bundle.parent=framework
 
-# To enable the use of the startup.properties file to control the start level:
-karaf.auto.start=startup.properties
-
 org.osgi.framework.startlevel.beginning=100
 karaf.startlevel.bundle=80
 

Modified: karaf/trunk/assemblies/features/framework/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
URL: http://svn.apache.org/viewvc/karaf/trunk/assemblies/features/framework/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/assemblies/features/framework/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg (original)
+++ karaf/trunk/assemblies/features/framework/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg Sun May  6 15:50:04 2012
@@ -95,5 +95,5 @@ org.ops4j.pax.url.mvn.defaultLocalRepoAs
 org.ops4j.pax.url.mvn.repositories= \
     http://repo1.maven.org/maven2@id=central, \
     http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases, \
-    file:${karaf.home}/${karaf.default.repository}
+    file:${karaf.home}/${karaf.default.repository}@id=systemrepo
 

Modified: karaf/trunk/itests/tests/src/test/resources/org/apache/karaf/testing/startup.properties
URL: http://svn.apache.org/viewvc/karaf/trunk/itests/tests/src/test/resources/org/apache/karaf/testing/startup.properties?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/itests/tests/src/test/resources/org/apache/karaf/testing/startup.properties (original)
+++ karaf/trunk/itests/tests/src/test/resources/org/apache/karaf/testing/startup.properties Sun May  6 15:50:04 2012
@@ -42,6 +42,5 @@ mvn\:org.apache.karaf.bundle/org.apache.
 mvn\:org.apache.karaf.bundle/org.apache.karaf.bundle.core/3.0.0-SNAPSHOT = 30
 mvn\:org.apache.karaf.system/org.apache.karaf.system.core/3.0.0-SNAPSHOT = 30
 mvn\:org.apache.karaf.system/org.apache.karaf.system.command/3.0.0-SNAPSHOT = 30
-mvn\:org.apache.karaf/org.apache.karaf.main/3.0.0-SNAPSHOT = 30
 mvn\:org.apache.karaf.shell/org.apache.karaf.shell.commands/3.0.0-SNAPSHOT = 30
 mvn\:org.apache.aries.quiesce/org.apache.aries.quiesce.api/0.3 = 30

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/ConfigProperties.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/ConfigProperties.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/ConfigProperties.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/ConfigProperties.java Sun May  6 15:50:04 2012
@@ -0,0 +1,226 @@
+package org.apache.karaf.main;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Properties;
+
+import org.apache.karaf.main.lock.SimpleFileLock;
+import org.apache.karaf.main.util.Utils;
+import org.osgi.framework.Constants;
+
+public class ConfigProperties {
+    /**
+     * 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";
+    /**
+     * The system property for hosting the current Karaf version.
+     */
+    public static final String PROP_KARAF_VERSION = "karaf.version";
+    /**
+     * The default name used for the configuration properties file.
+     */
+    private static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
+    /**
+     * The default name used for the system properties file.
+     */
+    public static final String SYSTEM_PROPERTIES_FILE_NAME = "system.properties";
+
+    /**
+     * Config property which identifies directories which contain bundles to be loaded by SMX
+     */
+    private static final String BUNDLE_LOCATIONS = "bundle.locations";
+    
+    /**
+     * The lock implementation
+     */
+    private static final String PROPERTY_LOCK_CLASS = "karaf.lock.class";
+
+    private static final String PROPERTY_LOCK_DELAY = "karaf.lock.delay";
+
+    private static final String PROPERTY_LOCK_LEVEL = "karaf.lock.level";
+
+    private static final String DEFAULT_REPO = "karaf.default.repository";
+    
+    private static final String KARAF_FRAMEWORK = "karaf.framework";
+
+    private static final String KARAF_FRAMEWORK_FACTORY = "karaf.framework.factory";
+
+    private static final String KARAF_SHUTDOWN_TIMEOUT = "karaf.shutdown.timeout";
+
+    private static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
+
+    private static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
+
+    private static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
+
+    private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
+
+    private static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file";
+
+    private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
+
+    private static final String PROPERTY_LOCK_CLASS_DEFAULT = SimpleFileLock.class.getName();
+
+    private static final String SECURITY_PROVIDERS = "org.apache.karaf.security.providers";
+
+    /**
+     * If a lock should be used before starting the runtime
+     */
+    private static final String PROPERTY_USE_LOCK = "karaf.lock";
+
+    File karafHome;
+    File karafBase;
+    File karafData;
+    File karafInstances;
+    
+    Properties props;
+    String[] securityProviders;
+    int defaultStartLevel = 100;
+    int lockStartLevel = 1;
+    int lockDelay = 1000;
+    int shutdownTimeout = 5 * 60 * 1000;
+    boolean useLock;
+    String lockClass;
+    String frameworkFactoryClass;
+    URI frameworkBundle;
+    String defaultRepo;
+    String bundleLocations;
+    int defaultBundleStartlevel;
+    String pidFile;
+    int shutdownPort;
+    String shutdownHost;
+    String portFile;
+    String shutdownCommand;
+    String includes;
+    String optionals;
+    File etcFolder;
+    
+    public ConfigProperties() throws Exception {
+        this.karafHome = Utils.getKarafHome(ConfigProperties.class, PROP_KARAF_HOME, ENV_KARAF_HOME);
+        this.karafBase = Utils.getKarafDirectory(PROP_KARAF_BASE, ENV_KARAF_BASE, karafHome, false, true);
+        this.karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+        
+        if (Boolean.getBoolean("karaf.restart.clean")) {
+            Utils.deleteDirectory(this.karafData);
+            this.karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+        }
+        
+        this.karafInstances = Utils.getKarafDirectory(PROP_KARAF_INSTANCES, ENV_KARAF_INSTANCES, new File(karafHome, "instances"), false, false);
+
+        Package p = Package.getPackage("org.apache.karaf.main");
+        if (p != null && p.getImplementationVersion() != null)
+            System.setProperty(PROP_KARAF_VERSION, p.getImplementationVersion());
+        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());
+
+        this.etcFolder = new File(karafBase, "etc");
+        if (!etcFolder.exists()) {
+            throw new FileNotFoundException("etc folder not found: " + etcFolder.getAbsolutePath());
+        }
+        PropertiesLoader.loadSystemProperties(new File(etcFolder, SYSTEM_PROPERTIES_FILE_NAME));
+
+        File file = new File(etcFolder, CONFIG_PROPERTIES_FILE_NAME);
+        this.props = PropertiesLoader.loadConfigProperties(file);
+        
+        String prop = props.getProperty(SECURITY_PROVIDERS);
+        this.securityProviders = (prop != null) ? prop.split(",") : new String[] {};
+        this.defaultStartLevel = Integer.parseInt(props.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
+        this.lockStartLevel = Integer.parseInt(props.getProperty(PROPERTY_LOCK_LEVEL, Integer.toString(lockStartLevel)));                
+        this.lockDelay = Integer.parseInt(props.getProperty(PROPERTY_LOCK_DELAY, Integer.toString(lockDelay)));
+        this.props.setProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, Integer.toString(lockStartLevel));
+        this.shutdownTimeout = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_TIMEOUT, Integer.toString(shutdownTimeout)));
+        this.useLock = Boolean.parseBoolean(props.getProperty(PROPERTY_USE_LOCK, "true"));
+        this.lockClass = props.getProperty(PROPERTY_LOCK_CLASS, PROPERTY_LOCK_CLASS_DEFAULT);
+        initFrameworkStorage(karafData);
+        this.frameworkFactoryClass = props.getProperty(KARAF_FRAMEWORK_FACTORY);
+        this.frameworkBundle = getFramework();
+        this.defaultRepo = System.getProperty(DEFAULT_REPO, "system");
+        this.bundleLocations = props.getProperty(BUNDLE_LOCATIONS);
+        this.defaultBundleStartlevel = getDefaultBundleStartLevel(60);
+        this.pidFile = props.getProperty(KARAF_SHUTDOWN_PID_FILE);
+        this.shutdownPort = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
+        this.shutdownHost = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
+        this.portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
+        this.shutdownCommand = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
+    }
+    
+    private String getProperyOrFail(String propertyName) {
+        String value = props.getProperty(propertyName);
+        if (value == null) {
+            throw new IllegalArgumentException("Property " + propertyName + " must be set in the etc/" + CONFIG_PROPERTIES_FILE_NAME + " configuration file");
+        }
+        return value;
+    }
+    
+    private URI getFramework() throws URISyntaxException {
+        String framework = getProperyOrFail(KARAF_FRAMEWORK);
+        String frameworkBundleUri = getProperyOrFail(KARAF_FRAMEWORK + "." + framework);
+        return new URI(frameworkBundleUri);
+    }
+
+    private void initFrameworkStorage(File karafData) throws Exception {
+        String frameworkStoragePath = props.getProperty(Constants.FRAMEWORK_STORAGE);
+        if (frameworkStoragePath == null) {
+            File storage = new File(karafData.getPath(), "cache");
+            try {
+                storage.mkdirs();
+            } catch (SecurityException se) {
+                throw new Exception(se.getMessage()); 
+            }
+            props.setProperty(Constants.FRAMEWORK_STORAGE, storage.getAbsolutePath());
+        }
+    }
+    
+    private int getDefaultBundleStartLevel(int ibsl) {
+        try {
+            String str = props.getProperty("karaf.startlevel.bundle");
+            if (str != null) {
+                ibsl = Integer.parseInt(str);
+            }
+        } catch (Throwable t) {
+        }
+        return ibsl;
+    }
+    
+}

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java Sun May  6 15:50:04 2012
@@ -0,0 +1,126 @@
+package org.apache.karaf.main;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+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.ServerSocket;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.launch.Framework;
+
+public class InstanceHelper {
+
+    static void updateInstancePid(File karafHome, File karafBase) {
+        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());
+        }
+    }
+
+    private static void writePid(String pidFile) {
+        try {
+            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();
+        }
+    }
+
+    static void setupShutdown(ConfigProperties config, Framework framework) {
+        writePid(config.pidFile);
+        try {
+            int port = config.shutdownPort;
+            String host = config.shutdownHost;
+            String portFile = config.portFile;
+            final String shutdown = config.shutdownCommand;
+            if (port >= 0) {
+                ServerSocket 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, shutdownSocket, framework);
+                thread.setDaemon(true);
+                thread.start();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/Main.java Sun May  6 15:50:04 2012
@@ -20,38 +20,27 @@ package org.apache.karaf.main;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 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.URI;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.security.Provider;
 import java.security.Security;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Enumeration;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
-import java.util.TreeMap;
 import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.karaf.info.ServerInfo;
 import org.apache.karaf.main.lock.Lock;
-import org.apache.karaf.main.lock.SimpleFileLock;
+import org.apache.karaf.main.lock.LockCallBack;
+import org.apache.karaf.main.lock.LockManager;
+import org.apache.karaf.main.lock.NoLock;
+import org.apache.karaf.main.util.ArtifactResolver;
 import org.apache.karaf.main.util.BootstrapLogManager;
-import org.apache.karaf.main.util.ServerInfoImpl;
 import org.apache.karaf.main.util.SimpleMavenResolver;
 import org.apache.karaf.main.util.StringMap;
 import org.apache.karaf.main.util.Utils;
@@ -78,293 +67,21 @@ import org.osgi.framework.startlevel.Fra
  */
 public class Main {
     /**
-     * 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 system property for hosting the current Karaf version.
-     */
-    public static final String PROP_KARAF_VERSION = "karaf.version";
-    /**
-     * 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}"; // mandatory includes
-    
-    public static final String OPTIONALS_PROPERTY = "${optionals}"; // optionals includes
-
-    public static final String SECURITY_PROVIDERS = "org.apache.karaf.security.providers";
 
     Logger LOG = Logger.getLogger(this.getClass().getName());
 
-    private File karafHome;
-    private File karafBase;
-    private File karafData;
-    private File karafInstances;
-    private Properties configProps = null;
+    private ConfigProperties config;
     private Framework framework = null;
     private final String[] args;
     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;
     private KarafActivatorManager activatorManager;
-
-
-    public Main(String[] args) {
-        this.args = args;
-    }
-
-    public void setShutdownCallback(ShutdownCallback shutdownCallback) {
-        this.shutdownCallback = shutdownCallback;
-    }
-
-    public void launch() throws Exception {
-        karafHome = Utils.getKarafHome(Main.class, Main.PROP_KARAF_HOME, Main.ENV_KARAF_HOME);
-        karafBase = Utils.getKarafDirectory(Main.PROP_KARAF_BASE, Main.ENV_KARAF_BASE, karafHome, false, true);
-        karafData = Utils.getKarafDirectory(Main.PROP_KARAF_DATA, Main.ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
-        
-        if (Boolean.getBoolean("karaf.restart.clean")) {
-            Utils.deleteDirectory(karafData);
-            karafData = Utils.getKarafDirectory(Main.PROP_KARAF_DATA, Main.ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
-        }
-        
-        karafInstances = Utils.getKarafDirectory(Main.PROP_KARAF_INSTANCES, Main.ENV_KARAF_INSTANCES, new File(karafHome, "instances"), false, false);
-
-        Package p = Package.getPackage("org.apache.karaf.main");
-        if (p != null && p.getImplementationVersion() != null)
-            System.setProperty(PROP_KARAF_VERSION, p.getImplementationVersion());
-        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());
-
-        PropertiesLoader.loadSystemProperties(karafBase);
-
-        updateInstancePid();
-
-        configProps = PropertiesLoader.loadConfigProperties(karafBase);
-        BootstrapLogManager.setProperties(configProps);
-        LOG.addHandler(BootstrapLogManager.getDefaultHandler());
-
-        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
-        ClassLoader classLoader = createClassLoader(configProps);
-        FrameworkFactory factory = loadFrameworkFactory(classLoader);
-        framework = factory.newFramework(new StringMap(configProps, false));
-        framework.init();
-        // Process properties
-        loadStartupProperties(configProps);
-        processAutoProperties(framework.getBundleContext());
-        framework.start();
-
-        ServerInfo serverInfo = new ServerInfoImpl(args, karafBase, karafData, karafHome, karafInstances);
-        framework.getBundleContext().registerService(ServerInfo.class, serverInfo, null);
-
-        // Start custom activators
-        activatorManager = new KarafActivatorManager(classLoader, framework);
-        activatorManager.startKarafActivators();
-        // Start lock monitor
-        new Thread() {
-            public void run() {
-                lock(configProps);
-            }
-        }.start();
-    }
-
-    private FrameworkFactory loadFrameworkFactory(ClassLoader classLoader) throws Exception {
-        String factoryClass = configProps.getProperty(KARAF_FRAMEWORK_FACTORY);
-        if (factoryClass == null) {
-            InputStream is = classLoader.getResourceAsStream("META-INF/services/" + FrameworkFactory.class.getName());
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-            factoryClass = br.readLine();
-            br.close();
-        }
-        FrameworkFactory factory = (FrameworkFactory) classLoader.loadClass(factoryClass).newInstance();
-        return factory;
-    }
-
-
-
-    public void awaitShutdown() throws Exception {
-        if (framework == null) {
-            return;
-        }
-        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 || framework.getState() == Bundle.STARTING) {
-                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) {
-                    activatorManager.stopKarafActivators();
-                    return true;
-                }
-            }
-            return false;
-        } finally {
-            unlock();
-        }
-    }
-
+    private LockManager lockManager;
+    
     /**
      * <p>
      * This method performs the main task of constructing an framework instance
@@ -479,227 +196,143 @@ public class Main {
         }
     }
 
-    private static void processSecurityProperties(Properties m_configProps) {
-        String prop = m_configProps.getProperty(SECURITY_PROVIDERS);
-        if (prop != null) {
-            String[] providers = prop.split(",");
-            for (String provider : providers) {
-                addProvider(provider);
+    public Main(String[] args) {
+        this.args = args;
+    }
+
+    public void setShutdownCallback(ShutdownCallback shutdownCallback) {
+        this.shutdownCallback = shutdownCallback;
+    }
+
+    public void launch() throws Exception {
+        config = new ConfigProperties();
+        InstanceHelper.updateInstancePid(config.karafHome, config.karafBase);
+        BootstrapLogManager.setProperties(config.props);
+        LOG.addHandler(BootstrapLogManager.getDefaultHandler());
+
+        for (String provider : config.securityProviders) {
+            addSecurityProvider(provider);
+        }
+        
+        List<File> bundleDirs = getBundleRepos();
+        ArtifactResolver resolver = new SimpleMavenResolver(bundleDirs);
+
+        // Start up the OSGI framework
+        ClassLoader classLoader = createClassLoader(resolver);
+        FrameworkFactory factory = loadFrameworkFactory(classLoader);
+        framework = factory.newFramework(new StringMap(config.props, false));
+        framework.init();
+        framework.start();
+
+        // If we have a clean state, install everything
+        if (framework.getBundleContext().getBundles().length == 1) {
+            installAndStartBundles(resolver);
+        }
+
+        ServerInfo serverInfo = new ServerInfoImpl(args, config);
+        framework.getBundleContext().registerService(ServerInfo.class, serverInfo, null);
+
+        activatorManager = new KarafActivatorManager(classLoader, framework);
+        activatorManager.startKarafActivators();
+        
+        Lock lock = createLock();
+        lockManager = new LockManager(lock, new KarafLockCallback(), config.lockDelay);
+        setStartLevel(config.lockStartLevel);
+        lockManager.startLockMonitor();
+    }
+    
+    private ClassLoader createClassLoader(ArtifactResolver resolver) throws Exception {
+        List<URL> urls = new ArrayList<URL>();
+        urls.add(resolver.resolve(config.frameworkBundle).toURL());
+        File[] libs = new File(config.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());
     }
-
-    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 FrameworkFactory loadFrameworkFactory(ClassLoader classLoader) throws Exception {
+        String factoryClass = config.frameworkFactoryClass;
+        if (factoryClass == null) {
+            InputStream is = classLoader.getResourceAsStream("META-INF/services/" + FrameworkFactory.class.getName());
+            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+            factoryClass = br.readLine();
+            br.close();
         }
+        FrameworkFactory factory = (FrameworkFactory) classLoader.loadClass(factoryClass).newInstance();
+        return factory;
     }
 
-    private void updateInstancePid() {
+    private Lock createLock() {
+        if (config.useLock) {
+            return new NoLock();
+        }
         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();
-                }
-            }
+            return (Lock) Lock.class.getClassLoader().loadClass(config.lockClass).getConstructor(Properties.class).newInstance(config.props);
         } catch (Exception e) {
-            System.err.println("Unable to update instance pid: " + e.getMessage());
+            throw new RuntimeException("Exception instantiating lock class " + config.lockClass, e);
         }
     }
 
-    /**
-     * <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.
-        FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
-
-        // Set the default bundle start level
-        int ibsl = 60;
+    private static void addSecurityProvider(String provider) {
         try {
-            String str = configProps.getProperty("karaf.startlevel.bundle");
-            if (str != null) {
-                ibsl = Integer.parseInt(str);
-            }
+            Security.addProvider((Provider) Class.forName(provider).newInstance());
         } catch (Throwable t) {
-        }
-        sl.setInitialBundleStartLevel(ibsl);
-
-        // If we have a clean state, install everything
-        if (framework.getBundleContext().getBundles().length == 1) {
-            // 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);
+            System.err.println("Unable to register security provider: " + t);
         }
     }
 
-    private List<Bundle> autoInstall(String propertyPrefix, BundleContext context, FrameworkStartLevel 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 = Utils.nextLocation(st);
-                    if (location != null) {
-                        try {
-                            String[] parts = Utils.convertToMavenUrlsIfNeeded(location, convertToMavenUrls);
-                            Bundle b = context.installBundle(parts[0], new URL(parts[1]).openStream());
-                            b.adapt(BundleStartLevel.class).setStartLevel(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);
-                }
+    private void installAndStartBundles(ArtifactResolver resolver) {
+        FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
+        sl.setInitialBundleStartLevel(config.defaultBundleStartlevel);
+        BundleContext context = framework.getBundleContext();
+        File startupPropsFile = new File(config.etcFolder, STARTUP_PROPERTIES_FILE_NAME);
+        Properties startupProps = PropertiesLoader.loadPropertiesOrFail(startupPropsFile);
+
+        LOG.info("Installing initial bundles");
+        
+        Enumeration<Object> keyIt = startupProps.keys();
+        while (keyIt.hasMoreElements()) {
+            String mvnUrl = (String) keyIt.nextElement();
+            String startlevelSt = startupProps.getProperty(mvnUrl).trim();
+            try {
+                Integer level = new Integer(startlevelSt);
+                URI resolvedURI = resolver.resolve(new URI(mvnUrl));
+                Bundle b = context.installBundle(mvnUrl, resolvedURI.toURL().openStream());
+                b.adapt(BundleStartLevel.class).setStartLevel(level);
+                if (isNotFragment(b)) {
+                    b.start();
+                }
+            } catch (Exception ex) {
+                throw new RuntimeException("Error installing bundle listed in " + STARTUP_PROPERTIES_FILE_NAME
+                        + " with url: " + mvnUrl + " and startlevel: " + startlevelSt, ex);
             }
         }
-        return bundles;
+        
+        LOG.info("All initial bundles started");
     }
 
-    private void loadStartupProperties(Properties configProps) 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.
+    private boolean isNotFragment(Bundle b) {
+        String fragmentHostHeader = (String) b.getHeaders().get(Constants.FRAGMENT_HOST);
+        return fragmentHostHeader == null || fragmentHostHeader.trim().length() == 0;
+    }
 
+    private List<File> getBundleRepos() {
         List<File> bundleDirs = new ArrayList<File>();
+        File baseSystemRepo = new File(config.karafHome, config.defaultRepo);
+        if (!baseSystemRepo.exists() && baseSystemRepo.isDirectory()) {
+            throw new RuntimeException("system repo folder not found: " + baseSystemRepo.getAbsolutePath());
+        }
+        bundleDirs.add(baseSystemRepo);
 
-        // See if the property URL was specified as a property.
-        URL startupPropURL;
+        File homeSystemRepo = new File(config.karafHome, config.defaultRepo);
+        bundleDirs.add(homeSystemRepo);
 
-        File etcFolder = new File(karafBase, "etc");
-        if (!etcFolder.exists()) {
-            throw new FileNotFoundException("etc folder not found: " + etcFolder.getAbsolutePath());
-        }
-        File file = new File(etcFolder, STARTUP_PROPERTIES_FILE_NAME);
-        startupPropURL = file.toURI().toURL();
-        Properties startupProps = PropertiesLoader.loadPropertiesFile(startupPropURL, true);
-
-        String defaultRepo = System.getProperty(DEFAULT_REPO, "system");
-        if (karafBase.equals(karafHome)) {
-            File systemRepo = new File(karafHome, defaultRepo);
-            if (!systemRepo.exists()) {
-                throw new FileNotFoundException("system repo not found: " + systemRepo.getAbsolutePath());
-            }
-            bundleDirs.add(systemRepo);
-        } else {
-            File baseSystemRepo = new File(karafBase, defaultRepo);
-            File homeSystemRepo = new File(karafHome, defaultRepo);
-            if (!baseSystemRepo.exists() && !homeSystemRepo.exists()) {
-                throw new FileNotFoundException("system repos not found: " + baseSystemRepo.getAbsolutePath() + " " + homeSystemRepo.getAbsolutePath());
-            }
-            bundleDirs.add(baseSystemRepo);
-            bundleDirs.add(homeSystemRepo);
-        }
-        String locations = configProps.getProperty(BUNDLE_LOCATIONS);
+        String locations = config.bundleLocations;
         if (locations != null) {
             StringTokenizer st = new StringTokenizer(locations, "\" ", true);
             if (st.countTokens() > 0) {
@@ -708,10 +341,10 @@ public class Main {
                     location = Utils.nextLocation(st);
                     if (location != null) {
                         File f;
-                        if (karafBase.equals(karafHome)) {
-                        	f = new File(karafHome, location);
+                        if (config.karafBase.equals(config.karafHome)) {
+                            f = new File(config.karafHome, location);
                         } else {
-                        	f = new File(karafBase, location);
+                            f = new File(config.karafBase, location);
                         }
                         if (f.exists() && f.isDirectory()) {
                             bundleDirs.add(f);
@@ -725,130 +358,7 @@ public class Main {
                 while (location != null);
             }
         }
-
-        // Mutate properties
-        Main.processConfigurationProperties(configProps, startupProps, bundleDirs);
-    }
-
-
-
-    private ClassLoader createClassLoader(Properties configProps) throws Exception {
-    	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 static void processConfigurationProperties(Properties configProps, Properties startupProps, List<File> bundleDirs) throws Exception {
-        if (bundleDirs == null) {
-            return;
-        }
-        boolean hasErrors = false;
-        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);
-            SimpleMavenResolver resolver = new SimpleMavenResolver(bundleDirs);
-            // 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.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);
-                    hasErrors = true;
-                }
-            }
-
-            for (Map.Entry<Integer, StringBuffer> entry : levels.entrySet()) {
-                configProps.setProperty(PROPERTY_AUTO_START + "." + entry.getKey(), entry.getValue().toString());
-            }
-        }
-        if (hasErrors) {
-            throw new Exception("Aborting due to missing startup bundles");
-        }
-    }
-
-
-    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);
-                }
-            }
-        }
+        return bundleDirs;
     }
 
     /**
@@ -871,104 +381,90 @@ public class Main {
     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();
-        }
+
+    protected void setStartLevel(int level) {
+        framework.adapt(FrameworkStartLevel.class).setStartLevel(level);
     }
 
-    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;
+    public void awaitShutdown() throws Exception {
+        if (framework == null) {
+            return;
+        }
+        while (true) {
+            FrameworkEvent event = framework.waitForStop(0);
+            if (event.getType() != FrameworkEvent.STOPPED_UPDATE) {
+                return;
             }
-            Thread.sleep(lockDelay);
         }
     }
 
-    public void unlock() throws Exception {
-        if (lock != null) {
-            lock.release();
+    public boolean destroy() throws Exception {
+        if (framework == null) {
+            return true;
         }
-    }
+        try {
+            int step = 5000;
 
-    protected void setStartLevel(int level) throws Exception {
-        framework.adapt(FrameworkStartLevel.class).setStartLevel(level);
-    }
+            // Notify the callback asap
+            if (shutdownCallback != null) {
+                shutdownCallback.waitingForShutdown(step);
+            }
 
-    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) {
-                ServerSocket shutdownSocket = new ServerSocket(port, 1, InetAddress.getByName(host));
-                if (port == 0) {
-                    port = shutdownSocket.getLocalPort();
+            lockManager.stopLockMonitor();
+
+            if (framework.getState() == Bundle.ACTIVE || framework.getState() == Bundle.STARTING) {
+                new Thread() {
+                    public void run() {
+                        try {
+                            framework.stop();
+                        } catch (BundleException e) {
+                            System.err.println("Error stopping karaf: " + e.getMessage());
+                        }
+                    }
+                }.start();
+            }
+
+            int timeout = config.shutdownTimeout;
+            if (config.shutdownTimeout <= 0) {
+                timeout = Integer.MAX_VALUE;
+            }
+            while (timeout > 0) {
+                timeout -= step;
+                if (shutdownCallback != null) {
+                    shutdownCallback.waitingForShutdown(step * 2);
                 }
-                if (portFile != null) {
-                    Writer w = new OutputStreamWriter(new FileOutputStream(portFile));
-                    w.write(Integer.toString(port));
-                    w.close();
+                FrameworkEvent event = framework.waitForStop(step);
+                if (event.getType() != FrameworkEvent.WAIT_TIMEDOUT) {
+                    activatorManager.stopKarafActivators();
+                    return true;
                 }
-                Thread thread = new ShutdownSocketThread(shutdown, shutdownSocket, framework);
-                thread.setDaemon(true);
-                thread.start();
             }
-        } catch (Exception e) {
-            e.printStackTrace();
+            return false;
+        } finally {
+            lockManager.stopLockMonitor();
         }
     }
-
-    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();
-                }
+    
+    private final class KarafLockCallback implements LockCallBack {
+        @Override
+        public void lockLost() {
+            if (framework.getState() == Bundle.ACTIVE) {
+                LOG.warning("Lock lost. Setting startlevel to " + config.lockStartLevel);
+                setStartLevel(config.lockStartLevel);
             }
-        } catch (Exception e) {
-            e.printStackTrace();
         }
-    }
 
+        @Override
+        public void lockAquired() {
+            LOG.info("Lock acquired. Setting startlevel to " + config.defaultStartLevel);
+            InstanceHelper.setupShutdown(config, framework);
+            setStartLevel(config.defaultStartLevel);
+        }
+
+        @Override
+        public void waitingForLock() {
+            LOG.fine("Waiting for the lock ...");
+        }
+    }
 
 }

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/PropertiesLoader.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/PropertiesLoader.java?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/PropertiesLoader.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/PropertiesLoader.java Sun May  6 15:50:04 2012
@@ -19,6 +19,7 @@
 package org.apache.karaf.main;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,6 +34,10 @@ import org.apache.karaf.main.util.Utils;
 
 public class PropertiesLoader {
 
+    private static final String INCLUDES_PROPERTY = "${includes}"; // mandatory includes
+    
+    private static final String OPTIONALS_PROPERTY = "${optionals}"; // optionals includes
+
     /**
      * <p>
      * Loads the configuration properties in the configuration property file
@@ -51,16 +56,10 @@ public class PropertiesLoader {
      * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
      * @throws Exception if something wrong occurs
      */
-    static Properties loadConfigProperties(File karafBase) throws Exception {
+    static Properties loadConfigProperties(File file) throws Exception {
         // See if the property URL was specified as a property.
         URL configPropURL;
-
         try {
-            File etcFolder = new File(karafBase, "etc");
-            if (!etcFolder.exists()) {
-                throw new FileNotFoundException("etc folder not found: " + etcFolder.getAbsolutePath());
-            }
-            File file = new File(etcFolder, Main.CONFIG_PROPERTIES_FILE_NAME);
             configPropURL = file.toURI().toURL();
         }
         catch (MalformedURLException ex) {
@@ -68,8 +67,8 @@ public class PropertiesLoader {
             return null;
         }
 
-
         Properties configProps = loadPropertiesFile(configPropURL, false);
+        copySystemProperties(configProps);
 
         // Perform variable substitution for system properties.
         for (Enumeration<?> e = configProps.propertyNames(); e.hasMoreElements();) {
@@ -78,7 +77,6 @@ public class PropertiesLoader {
                     SubstHelper.substVars(configProps.getProperty(name), name, null, configProps));
         }
 
-        copySystemProperties(configProps);
         return configProps;
     }
     
@@ -97,48 +95,18 @@ public class PropertiesLoader {
      * </p>
      *
      * @param karafBase the karaf base folder
+     * @throws IOException 
      */
-    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"), Main.SYSTEM_PROPERTIES_FILE_NAME);
-            propURL = file.toURI().toURL();
-        }
-        catch (MalformedURLException ex) {
-            System.err.print("Main: " + ex);
-            return;
-        }
-    
-        // Read the properties file.
+    static void loadSystemProperties(File file) throws IOException {
         Properties props = new Properties();
-        InputStream is = null;
         try {
-            is = propURL.openConnection().getInputStream();
+            InputStream is = new FileInputStream(file);
             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;
+        } catch (Exception e1) {
+            // Ignore
         }
     
-        // 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));
@@ -158,8 +126,16 @@ public class PropertiesLoader {
         }
     }
     
-    static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
-        // Read the properties file.
+    static Properties loadPropertiesOrFail(File configFile) {
+        try {
+            URL configPropURL = configFile.toURI().toURL();
+            return loadPropertiesFile(configPropURL, true);
+        } catch (Exception e) {
+            throw new RuntimeException("Error loading properties from " + configFile, e);
+        }
+    }
+    
+    private static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
         Properties configProps = new Properties();
         InputStream is = null;
         try {
@@ -186,7 +162,15 @@ public class PropertiesLoader {
                 // Nothing we can do.
             }
         }
-        String includes = configProps.getProperty(Main.INCLUDES_PROPERTY);
+        loadIncludes(INCLUDES_PROPERTY, true, configPropURL, configProps);
+        loadIncludes(OPTIONALS_PROPERTY, false, configPropURL, configProps);
+        trimValues(configProps);
+        return configProps;
+    }
+
+    private static void loadIncludes(String propertyName, boolean mandatory, URL configPropURL, Properties configProps)
+            throws MalformedURLException, Exception {
+        String includes = (String) configProps.get(propertyName);
         if (includes != null) {
             StringTokenizer st = new StringTokenizer(includes, "\" ", true);
             if (st.countTokens() > 0) {
@@ -195,30 +179,17 @@ public class PropertiesLoader {
                     location = Utils.nextLocation(st);
                     if (location != null) {
                         URL url = new URL(configPropURL, location);
-                        Properties props = loadPropertiesFile(url, true);
+                        Properties props = loadPropertiesFile(url, mandatory);
                         configProps.putAll(props);
                     }
                 }
                 while (location != null);
             }
-            configProps.remove(Main.INCLUDES_PROPERTY);
-        }
-        String optionals = configProps.getProperty(Main.OPTIONALS_PROPERTY);
-        if (optionals != null) {
-            StringTokenizer st = new StringTokenizer(optionals, "\" ", true);
-            if (st.countTokens() > 0) {
-                String location;
-                do {
-                    location = Utils.nextLocation(st);
-                    if (location != null) {
-                        URL url = new URL(configPropURL, location);
-                        Properties props = loadPropertiesFile(url, false);
-                        configProps.putAll(props);
-                    }
-                } while (location != null);
-            }
-            configProps.remove(Main.OPTIONALS_PROPERTY);
         }
+        configProps.remove(propertyName);
+    }
+
+    private static void trimValues(Properties configProps) {
         for (Enumeration<?> e = configProps.propertyNames(); e.hasMoreElements();) {
             Object key = e.nextElement();
             if (key instanceof String) {
@@ -226,6 +197,5 @@ public class PropertiesLoader {
                 configProps.put(key, v.trim());
             }
         }
-        return configProps;
     }
 }

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/ServerInfoImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/ServerInfoImpl.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/ServerInfoImpl.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/ServerInfoImpl.java Sun May  6 15:50:04 2012
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.main;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.karaf.info.ServerInfo;
+
+/**
+ * @version $Rev: 1209819 $ $Date: 2011-12-03 02:35:52 +0100 (Sa, 03 Dez 2011) $
+ */
+public class ServerInfoImpl implements ServerInfo {
+
+    private final String[] args;
+    private final ConfigProperties config;
+
+    public ServerInfoImpl(String[] args, ConfigProperties config) {
+        this.args = args;
+        this.config = config;
+    }
+
+    @Override
+    public File getHomeDirectory() {
+        return config.karafHome;
+    }
+
+    @Override
+    public String resolveHomePath(String filename) {
+        return resolveWithBase(config.karafHome, filename).getAbsolutePath();
+    }
+
+    @Override
+    public File resolveHome(String filename) {
+        return resolveWithBase(config.karafHome, filename);
+    }
+
+    @Override
+    public URI resolveHome(URI uri) {
+        return config.karafHome.toURI().resolve(uri);
+    }
+
+    @Override
+    public File getBaseDirectory() {
+        return config.karafBase;
+    }
+
+    @Override
+    public String resolveBasePath(String filename) {
+        return resolveWithBase(config.karafBase, filename).getAbsolutePath();
+    }
+
+    @Override
+    public File resolveBase(String filename) {
+        return resolveWithBase(config.karafBase, filename);
+    }
+
+    @Override
+    public URI resolveBase(URI uri) {
+        return config.karafBase.toURI().resolve(uri);
+    }
+
+    @Override
+    public File getDataDirectory() {
+        return config.karafData;
+    }
+
+    @Override
+    public File getInstancesDirectory() {
+        return config.karafInstances;
+    }
+
+    @Override
+    public String[] getArgs() {
+        return args.clone();
+    }
+
+    private File resolveWithBase(File baseDir, String filename) {
+        File file = new File(filename);
+        if (file.isAbsolute()) {
+            return file;
+        }
+        return new File(baseDir, filename);
+    }
+
+}

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/Stop.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/Stop.java?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/Stop.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/Stop.java Sun May  6 15:50:04 2012
@@ -19,15 +19,11 @@
 package org.apache.karaf.main;
 
 import java.io.BufferedReader;
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.Socket;
-import java.util.Properties;
-
-import org.apache.karaf.main.util.Utils;
 
 /**
  * Main class used to stop the root Karaf instance
@@ -42,29 +38,13 @@ public class Stop {
      * @throws Exception
      */
     public static void main(String[] args) throws Exception {
-        File karafHome = Utils.getKarafHome(Stop.class, Main.PROP_KARAF_HOME, Main.ENV_KARAF_HOME);
-        File karafBase = Utils.getKarafDirectory(Main.PROP_KARAF_BASE, Main.ENV_KARAF_BASE, karafHome, false, true);
-        File karafData = Utils.getKarafDirectory(Main.PROP_KARAF_DATA, Main.ENV_KARAF_DATA, new File(karafBase.getPath(), "data"), true, true);
-
-        System.setProperty(Main.PROP_KARAF_HOME, karafHome.getPath());
-        System.setProperty(Main.PROP_KARAF_BASE, karafBase.getPath());
-        System.setProperty(Main.PROP_KARAF_DATA, karafData.getPath());
-
-        // Load system properties.
-        PropertiesLoader.loadSystemProperties(karafBase);
-
-        Properties props = PropertiesLoader.loadConfigProperties(karafBase);
-
-        int port = Integer.parseInt(props.getProperty(Main.KARAF_SHUTDOWN_PORT, "0"));
-        String host = props.getProperty(Main.KARAF_SHUTDOWN_HOST, "localhost");
-        String portFile = props.getProperty(Main.KARAF_SHUTDOWN_PORT_FILE);
-        String shutdown = props.getProperty(Main.KARAF_SHUTDOWN_COMMAND, Main.DEFAULT_SHUTDOWN_COMMAND);
-        if (port == 0 && portFile != null) {
-            port = getPortFromShutdownPortFile(portFile);
+        ConfigProperties config = new ConfigProperties();
+        if (config.shutdownPort == 0 && config.portFile != null) {
+            config.shutdownPort = getPortFromShutdownPortFile(config.portFile);
         }
-        if (port > 0) {
-            Socket s = new Socket(host, port);
-            s.getOutputStream().write(shutdown.getBytes());
+        if (config.shutdownPort > 0) {
+            Socket s = new Socket(config.shutdownHost, config.shutdownPort);
+            s.getOutputStream().write(config.shutdownCommand.getBytes());
             s.close();
         } else {
             System.err.println("Unable to find port...");

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockCallBack.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockCallBack.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockCallBack.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockCallBack.java Sun May  6 15:50:04 2012
@@ -0,0 +1,10 @@
+package org.apache.karaf.main.lock;
+
+/**
+ * Allows to react on events generated by the locking framework
+ */
+public interface LockCallBack {
+    void lockAquired();
+    void lockLost();
+    void waitingForLock();
+}

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/lock/LockManager.java Sun May  6 15:50:04 2012
@@ -0,0 +1,70 @@
+package org.apache.karaf.main.lock;
+
+
+public class LockManager {
+    private Lock lock;
+    private boolean exiting = false;
+
+    /**
+     * 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_CLASS_DEFAULT = SimpleFileLock.class.getName();
+    private final LockCallBack lockCallback;
+    private final int lockCheckInterval;
+    
+	public LockManager(Lock lock, LockCallBack lockCallback, int lockCheckIntervalSeconds) {
+	    this.lock = lock;
+        this.lockCallback = lockCallback;
+        this.lockCheckInterval = lockCheckIntervalSeconds;
+	}
+	
+    public void startLockMonitor() {
+        new Thread() {
+            public void run() {
+                runLockManager();
+            }
+        }.start();
+    }
+    
+    public void stopLockMonitor() {
+        this.exiting = true;
+    }
+    
+    private void runLockManager() {
+        while (!exiting) {
+            try {
+                if (lock.lock()) {
+                    lockCallback.lockAquired();
+                    for (;;) {
+                        if (!lock.isAlive() || exiting) {
+                            break;
+                        }
+                        Thread.sleep(lockCheckInterval);
+                    }
+                    if (!exiting) {
+                        lockCallback.lockLost();
+                    }
+                } else {
+                    lockCallback.waitingForLock();
+                }
+                Thread.sleep(lockCheckInterval);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+    
+    public void unlock() throws Exception {
+        lock.release();
+    }
+
+}

Added: karaf/trunk/main/src/main/java/org/apache/karaf/main/util/ArtifactResolver.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/util/ArtifactResolver.java?rev=1334671&view=auto
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/util/ArtifactResolver.java (added)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/util/ArtifactResolver.java Sun May  6 15:50:04 2012
@@ -0,0 +1,7 @@
+package org.apache.karaf.main.util;
+
+import java.net.URI;
+
+public interface ArtifactResolver {
+    URI resolve(URI artifactUri);
+}

Modified: karaf/trunk/main/src/main/java/org/apache/karaf/main/util/SimpleMavenResolver.java
URL: http://svn.apache.org/viewvc/karaf/trunk/main/src/main/java/org/apache/karaf/main/util/SimpleMavenResolver.java?rev=1334671&r1=1334670&r2=1334671&view=diff
==============================================================================
--- karaf/trunk/main/src/main/java/org/apache/karaf/main/util/SimpleMavenResolver.java (original)
+++ karaf/trunk/main/src/main/java/org/apache/karaf/main/util/SimpleMavenResolver.java Sun May  6 15:50:04 2012
@@ -19,6 +19,7 @@
 package org.apache.karaf.main.util;
 
 import java.io.File;
+import java.net.URI;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -26,7 +27,7 @@ import java.util.regex.Pattern;
 /**
  * Resolves local maven artifacts and raw file paths
  */
-public class SimpleMavenResolver {
+public class SimpleMavenResolver implements ArtifactResolver {
     private static final Pattern mvnPattern = Pattern.compile("mvn:([^/ ]+)/([^/ ]+)/([^/ ]*)(/([^/ ]+)(/([^/ ]+))?)?");
     private final List<File> mavenRepos;
 
@@ -46,21 +47,21 @@ public class SimpleMavenResolver {
      * If artifactUri does not match the Syntax the local file that corresponds to the path is returned
      * 
      * @param artifactUri Maven artifact URI
-     * @return file referenced by the URI
+     * @return resolved URI
      */
-    public File resolve(String artifactUri) {
+    public URI resolve(URI artifactUri) {
         for (File bundleDir : mavenRepos) {
             File file = findFile(bundleDir, artifactUri);
             if (file != null) {
-                return file;
+                return file.toURI();
             }
         }
-        return null;
+        throw new RuntimeException("Could not resolve " + artifactUri);
     }
 
-    private static File findFile(File dir, String name) {
-        name = fromMaven(name);
-        File theFile = new File(dir, name);
+    private static File findFile(File dir, URI mvnUri) {
+        String path = fromMaven(mvnUri);
+        File theFile = new File(dir, path);
 
         if (theFile.exists() && !theFile.isDirectory()) {
             return theFile;
@@ -80,10 +81,10 @@ public class SimpleMavenResolver {
      * @param name input artifact info
      * @return path as supplied or a default maven repo path
      */
-    private static String fromMaven(String name) {
-        Matcher m = mvnPattern.matcher(name);
+    private static String fromMaven(URI name) {
+        Matcher m = mvnPattern.matcher(name.toString());
         if (!m.matches()) {
-            return name;
+            return name.toString();
         }
         StringBuilder b = new StringBuilder();
         b.append(m.group(1));