/*
 * 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.sling.launchpad.base.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.felix.framework.Logger;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.sling.launchpad.api.LaunchpadContentProvider;
import org.apache.sling.launchpad.base.shared.Notifiable;
import org.apache.sling.launchpad.base.shared.SharedConstants;
import org.apache.sling.launchpad.base.shared.Util;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
import org.osgi.service.url.URLConstants;
import org.osgi.service.url.URLStreamHandlerService;

/**
 * The <code>Sling</code> serves as the starting point for Sling.
 * <ul>
 * <li>The {@link #Sling(Notifiable, Logger, LaunchpadContentProvider, Map)} method launches Apache
 * <code>Felix</code> as the OSGi framework implementation we use.
 * </ul>
 * <p>
 * <b>Launch Configuration</b>
 * <p>
 * The Apache <code>Felix</code> framework requires configuration parameters to
 * be specified for startup. This servlet builds the list of parameters from
 * three locations:
 * <ol>
 * <li>The <code>sling.properties</code> file is read from the servlet class
 * path. This properties file contains default settings.</li>
 * <li>Extensions of this servlet may provide additional properties to be loaded
 * overwriting the {@link #loadPropertiesOverride(Map)} method.
 * <li>Finally, web application init parameters are added to the properties and
 * may overwrite existing properties of the same name(s).
 * </ol>
 * <p>
 * After loading all properties, variable substitution takes place on the
 * property values. A variable is indicated as <code>${&lt;prop-name&gt;}</code>
 * where <code>&lt;prop-name&gt;</code> is the name of a system or configuration
 * property (configuration properties override system properties). Variables may
 * be nested and are resolved from inner-most to outer-most. For example, the
 * property value <code>${outer-${inner}}</code> is resolved by first resolving
 * <code>${inner}</code> and then resolving the property whose name is the
 * catenation of <code>outer-</code> and the result of resolving
 * <code>${inner}</code>.
 * <p>
 */
public class Sling {

    /**
     * The name of the configuration property defining the Sling home directory
     * as an URL (value is "sling.home.url").
     * <p>
     * The value of this property is assigned the value of
     * <code>new File(${sling.home}).toURI().toString()</code> before
     * resolving the property variables.
     *
     * @see SharedConstants#SLING_HOME
     */
    public static final String SLING_HOME_URL = "sling.home.url";

    /**
     * The name of the configuration property defining the JCR home directory
     * (value is "sling.repository.home").
     * <p>
     * The value of this property could be set as a system property, init-param in
     * web.xml or property in sling.properties.
     * <p>
     * Default value to #SLING_HOME/repository_name
     */
    public static final String JCR_REPO_HOME = "sling.repository.home";

    /**
     * The name of the configuration property defining the URL of an existing
     * repository config file (repository.xml).
     * <p>
     * The value of this property could be set as a system property, init-param in
     * web.xml or property in sling.properties.
     * <p>
     * Default value to #SLING_HOME/repository_name/repository.xml
     */
    public static final String JCR_REPO_CONFIG_FILE_URL = "sling.repository.config.file.url";

    /**
     * The name of the configuration property defining a properties file
     * defining a list of bundles, which are installed into the framework when
     * it has been launched (value is "org.apache.osgi.bundles").
     * <p>
     * This configuration property is generally set in the web application
     * configuration and may be referenced in all property files (default, user
     * supplied and web application parameters) used to build the framework
     * configuration.
     */
    public static final String OSGI_FRAMEWORK_BUNDLES = "org.apache.osgi.bundles";

    /**
     * The property to be set to ignore the system properties when building the
     * Felix framework properties (value is "sling.ignoreSystemProperties"). If
     * this is property is set to <code>true</code> (case does not matter),
     * the system properties will not be used by
     * {@link #loadConfigProperties(Map)}.
     */
    public static final String SLING_IGNORE_SYSTEM_PROPERTIES = "sling.ignoreSystemProperties";

    /**
     * The name of the default launcher properties file to setup the environment
     * for the <code>Felix</code> framework (value is "sling.properties").
     * <p>
     * Extensions of this class may overwrite some or all properties in this
     * file through Web Application parameters or other properties files.
     */
    public static final String CONFIG_PROPERTIES = "sling.properties";

    public static final String PROP_SYSTEM_PACKAGES = "org.apache.sling.launcher.system.packages";

    public static final String PROP_EXTRA_CAPS = "org.apache.sling.launcher.system.capabilities.extra";

    /**
     * Timeout to wait for the initialized framework to actually stop for it to
     * be reinitialized. This is set to a second, which should be ample time to
     * do this. If this time passes without the framework being stopped, an
     * error is issued.
     */
    private static final long REINIT_TIMEOUT = 1000L;

    /**
     * The simple logger to log messages during startup and shutdown to
     */
    protected final Logger logger;

    private LaunchpadContentProvider resourceProvider;

    /**
     * The <code>Felix</code> instance loaded on {@link #init()} and stopped
     * on {@link #destroy()}.
     */
    private Framework framework;

    /**
     * Initializes this servlet by loading the framework configuration
     * properties, starting the OSGi framework (Apache Felix) and exposing the
     * system bundle context and the <code>Felix</code> instance as servlet
     * context attributes.
     *
     * @throws BundleException if the framework cannot be initialized.
     */
    public Sling(final Notifiable notifiable,
            final Logger logger,
            final LaunchpadContentProvider resourceProvider,
            final Map<String, String> propOverwrite)
    throws BundleException {

        this.logger = logger;
        this.resourceProvider = resourceProvider;

        final long startedAt = System.currentTimeMillis();
        this.logger.log(Logger.LOG_INFO, "Starting Apache Sling");

        // read the default parameters
        final Map<String, String> props = this.loadConfigProperties(propOverwrite);

        // check for bootstrap command file
        copyBootstrapCommandFile(props);

        // create the framework and start it
        try {

            // initiate startup handler
            final StartupManager startupManager = new StartupManager(props, logger);

            Framework tmpFramework = createFramework(notifiable, logger, props);
            init(tmpFramework);

            final boolean restart = new BootstrapInstaller(tmpFramework.getBundleContext(), logger,
                    resourceProvider, startupManager.getMode()).install();
            startupManager.markInstalled();

            if (restart) {
                restart(tmpFramework);
                tmpFramework = createFramework(notifiable, logger, props);
                init(tmpFramework);
            }

            new DefaultStartupHandler(tmpFramework.getBundleContext(), logger, startupManager, startedAt);

            // finally start
            tmpFramework.start();

            // only assign field if start succeeds
            this.framework = tmpFramework;
        } catch (final BundleException be) {
            throw be;
        } catch (final Exception e) {
            // thrown by SlingFelix constructor
            throw new BundleException("Uncaught Instantiation Issue: " + e, e);
        }

        // log sucess message
        this.logger.log(Logger.LOG_INFO, "Apache Sling started");
    }

    /**
     * Destroys this servlet by shutting down the OSGi framework and hence the
     * delegatee servlet if one is set at all.
     */
    public final void destroy() {
        if (framework != null) {
            // get a private copy of the reference and remove the class ref
            Framework myFramework;
            synchronized (this) {
                myFramework = framework;
                framework = null;
            }

            // shutdown the Felix container
            if (myFramework != null) {
                logger.log(Logger.LOG_INFO, "Shutting down Apache Sling");
                try {

                    myFramework.stop();
                    myFramework.waitForStop(0);

                } catch (BundleException be) {

                    // may be thrown by stop, log but continue
                    logger.log(Logger.LOG_ERROR,
                        "Failure initiating Framework Shutdown", be);

                } catch (InterruptedException ie) {

                    // may be thrown by waitForStop, log but continue
                    logger.log(
                        Logger.LOG_ERROR,
                        "Interrupted while waiting for the Framework Termination",
                        ie);

                }

                logger.log(Logger.LOG_INFO, "Apache Sling stopped");
            }
        }
    }

    // ---------- BundleActivator ----------------------------------------------

    /**
     * Called when the OSGi framework is being started. This implementation
     * registers as a service listener for the
     * <code>javax.servlet.Servlet</code> class and calls the
     * {@link #doStartBundle()} method for implementations to execute more
     * startup tasks. Additionally the <code>context</code> URL protocol
     * handler is registered.
     *
     * @param bundleContext The <code>BundleContext</code> of the system
     *            bundle of the OSGi framework.
     * @throws BundleException May be thrown if the {@link #doStartBundle()} throws.
     */
    private final void startup(BundleContext bundleContext) {

        // register the context URL handler
        Hashtable<String, Object> props = new Hashtable<String, Object>();
        props.put(URLConstants.URL_HANDLER_PROTOCOL, new String[] { "context" });
        ContextProtocolHandler contextHandler = new ContextProtocolHandler(
            this.resourceProvider);
        bundleContext.registerService(URLStreamHandlerService.class.getName(),
            contextHandler, props);

        // register the platform MBeanServer
        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
        Hashtable<String, Object> mbeanProps = new Hashtable<String, Object>();
        try {
            ObjectName beanName = ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");
            AttributeList attrs = platformMBeanServer.getAttributes(beanName,
                new String[] { "MBeanServerId", "SpecificationName",
                    "SpecificationVersion", "SpecificationVendor",
                    "ImplementationName", "ImplementationVersion",
                    "ImplementationVendor" });
            for (Object object : attrs) {
                Attribute attr = (Attribute) object;
                if (attr.getValue() != null) {
                    mbeanProps.put(attr.getName(), attr.getValue().toString());
                }
            }
        } catch (Exception je) {
            logger.log(
                Logger.LOG_INFO,
                "start: Cannot set service properties of Platform MBeanServer service, registering without",
                je);
        }
        bundleContext.registerService(MBeanServer.class.getName(),
            platformMBeanServer, mbeanProps);
        bundleContext.registerService(LaunchpadContentProvider.class.getName(), resourceProvider, null);
    }

    // ---------- Creating the framework instance

    @SuppressWarnings("unchecked")
    private Framework createFramework(final Notifiable notifiable,
            final Logger logger, @SuppressWarnings("rawtypes") Map props)
            throws Exception {
        props.put(FelixConstants.LOG_LOGGER_PROP, logger);
        return new SlingFelix(notifiable, props);
    }

    private void init(final Framework framework) throws BundleException {
        // initialize the framework
        framework.init();

        // do first startup setup
        this.startup(framework.getBundleContext());
    }

    private void restart(final Framework framework) throws BundleException {
        if ((framework.getState() & (Bundle.STARTING|Bundle.ACTIVE|Bundle.STOPPING)) != 0) {
            if ( framework instanceof SlingFelix ) {
                ((SlingFelix)framework).restart();
            } else {
                framework.stop();
            }
            try {
                framework.waitForStop(REINIT_TIMEOUT);
            } catch (InterruptedException ie) {
                throw new BundleException(
                    "Interrupted while waiting for the framework stop before reinitialization");
            }
        }
    }

    // ---------- Configuration Loading

    /**
     * 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>framework.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>framework.config.properties</tt>" system
     * property to an arbitrary URL.
     *
     * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was
     *         an error.
     */
    private Map<String, String> loadConfigProperties(
            final Map<String, String> propOverwrite) throws BundleException {
        // The config 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.
        final Map<String, String> staticProps = new HashMap<String, String>();

        // Read the embedded (default) properties file.
        this.load(staticProps, CONFIG_PROPERTIES);

        // resolve inclusions (and remove property)
        this.loadIncludes(staticProps, null);

        // overwrite default properties with initial overwrites
        if (propOverwrite != null) {
            staticProps.putAll(propOverwrite);
        }

        // check whether sling.home is overwritten by system property
        String slingHome = staticProps.get(SharedConstants.SLING_HOME);
        if (slingHome == null || slingHome.length() == 0) {
            throw new BundleException("sling.home property is missing, cannot start");
        }

        // resolve variables and ensure sling.home is an absolute path
        slingHome = Util.substVars(slingHome, SharedConstants.SLING_HOME, null, staticProps);
        File slingHomeFile = new File(slingHome).getAbsoluteFile();
        slingHome = slingHomeFile.getAbsolutePath();

        // overlay with ${sling.home}/sling.properties
        this.logger.log(Logger.LOG_INFO, "Starting Apache Sling in " + slingHome);
        File propFile = getSlingProperties(slingHome, staticProps);
        this.load(staticProps, propFile);

        // migrate old properties to new properties
        migrateProp(staticProps, "framework.cache.profiledir", Constants.FRAMEWORK_STORAGE);
        migrateProp(staticProps, "sling.osgi-core-packages", "osgi-core-packages");
        migrateProp(staticProps, "sling.osgi-compendium-services", "osgi-compendium-services");

        // migrate initial start level property: Felix used to have
        // framework.startlevel.framework, later moved to org.osgi.framework.startlevel
        // and finally now uses org.osgi.framework.startlevel.beginning as
        // speced in the latest R 4.2 draft (2009/03/10). We first check the
        // intermediate Felix property, then the initial property, thus allowing
        // the older (and more probable value) to win
        migrateProp(staticProps, "org.osgi.framework.startlevel", Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
        migrateProp(staticProps, "framework.startlevel.framework", Constants.FRAMEWORK_BEGINNING_STARTLEVEL);

        // create a copy of the properties to perform variable substitution
        final Map<String, String> runtimeProps = new HashMap<String, String>();
        runtimeProps.putAll(staticProps);

        // check system properties for any overrides (except sling.home !)
        String ignoreSystemProperties = runtimeProps.get(SLING_IGNORE_SYSTEM_PROPERTIES);
        if (!"true".equalsIgnoreCase(ignoreSystemProperties)) {
            for (String name : runtimeProps.keySet()) {
                String sysProp = System.getProperty(name);
                if (sysProp != null) {
                    runtimeProps.put(name, sysProp);
                }
            }
        }

        // resolve inclusions again
        this.loadIncludes(runtimeProps, slingHome);

        // overwrite properties, this is not persisted as such
        this.loadPropertiesOverride(runtimeProps);

        // resolve boot delegation and system packages
        this.resolve(runtimeProps, "org.osgi.framework.bootdelegation",
            "sling.bootdelegation.");
        this.resolve(runtimeProps, "org.osgi.framework.system.packages",
            "sling.system.packages.");

        // reset back the sling home property
        // might have been overwritten by system properties, included
        // files or the sling.properties file
        staticProps.put(SharedConstants.SLING_HOME, slingHome);
        runtimeProps.put(SharedConstants.SLING_HOME, slingHome);
        runtimeProps.put(SLING_HOME_URL, slingHomeFile.toURI().toString());

        // add property file locations
        runtimeProps.put(SharedConstants.SLING_PROPERTIES, propFile.getAbsolutePath());
        runtimeProps.put(SharedConstants.SLING_PROPERTIES_URL, propFile.toURI().toString());

        // Perform variable substitution for system properties.
        for (Entry<String, String> entry : runtimeProps.entrySet()) {
            entry.setValue(Util.substVars(entry.getValue(), entry.getKey(), null,
                runtimeProps));
        }

        // look for context:/ URLs to substitute
        for (Entry<String, String> entry : runtimeProps.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            if (value != null && value.startsWith("context:/")) {
                String path = value.substring("context:/".length() - 1);

                InputStream src = this.resourceProvider.getResourceAsStream(path);
                if (src != null) {
                    File target = new File(slingHome, path);
                    OutputStream dest = null;
                    try {
                        // only copy file if not existing
                        if (!target.exists()) {
                            target.getParentFile().mkdirs();
                            dest = new FileOutputStream(target);
                            byte[] buf = new byte[2048];
                            int rd;
                            while ((rd = src.read(buf)) >= 0) {
                                dest.write(buf, 0, rd);
                            }
                        }

                        // after copying replace property and add url property
                        entry.setValue(target.getAbsolutePath());

                        // also set the new property on the unsubstituted props
                        staticProps.put(name, "${sling.home}" + path);

                    } catch (IOException ioe) {
                        this.logger.log(Logger.LOG_ERROR, "Cannot copy file "
                            + value + " to " + target, ioe);
                    } finally {
                        if (dest != null) {
                            try {
                                dest.close();
                            } catch (IOException ignore) {
                            }
                        }
                        try {
                            src.close();
                        } catch (IOException ignore) {
                        }
                    }
                }
            }
        }

        // write the unsubstituted properties back to the overlay file
        OutputStream os = null;
        try {
            // ensure parent folder(s)
            propFile.getParentFile().mkdirs();

            os = new FileOutputStream(propFile);

            // copy the values into a temporary properties structure to store
            Properties tmp = new Properties();
            tmp.putAll(staticProps);

            // remove properties where overlay makes no sense
            tmp.remove(SharedConstants.SLING_HOME);
            tmp.remove(SharedConstants.SLING_LAUNCHPAD);
            tmp.remove(SharedConstants.SLING_PROPERTIES);

            tmp.store(os, "Overlay properties for configuration");
        } catch (Exception ex) {
            this.logger.log(Logger.LOG_ERROR,
                "Error loading overlay properties from " + propFile, ex);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException ex2) {
                    // Nothing we can do.
                }
            }
        }

        return runtimeProps;
    }

    /**
     * Scans the properties for any properties starting with the given
     * <code>prefix</code> (e.g. <code>sling.bootdelegation.</code>).
     * <ol>
     * <li>Each such property is checked, whether it actually starts with
     * <code>prefix<b>class.</b></code>. If so, the rest of the property
     * name is assumed to be a fully qualified class name which is check,
     * whether it is visible. If so, the value of the property is appended to
     * the value of the <code>osgiProp</code>. If the class cannot be loaded,
     * the property is ignored.
     * <li>Otherwise, if the property does not contain a fully qualified class
     * name, the value of the property is simply appended to the
     * <code>osgiProp</code>.
     * </ol>
     *
     * @param props The <code>Properties</code> to be scanned.
     * @param osgiProp The name of the property in <code>props</code> to which
     *            any matching property values are appended.
     * @param prefix The prefix of properties to handle.
     */
    private void resolve(Map<String, String> props, String osgiProp,
            String prefix) {
        final String propVal = props.get(osgiProp);
        StringBuffer prop = new StringBuffer(propVal == null ? "" : propVal);
        boolean mod = false;
        for (Entry<String, String> pEntry : props.entrySet()) {
            String key = pEntry.getKey();
            if (key.startsWith(prefix)) {
                if (key.indexOf("class.") == prefix.length()) {
                    // prefix is followed by checker class name
                    String className = key.substring(prefix.length()
                        + "class.".length());
                    try {
                        this.getClass().getClassLoader().loadClass(className);
                    } catch (Throwable t) {
                        // don't really care, but class checking failed, so we
                        // do not add
                        this.logger.log(Logger.LOG_DEBUG, "Class " + className
                            + " not found. Ignoring '" + pEntry.getValue()
                            + "' for property " + osgiProp);
                        continue;
                    }
                }

                // get here if class is known or no checker class
                this.logger.log(Logger.LOG_DEBUG, "Adding '"
                    + pEntry.getValue() + "' to property " + osgiProp);
                if (prop.length() > 0) {
                    prop.append(',');
                }
                prop.append(pEntry.getValue());
                mod = true;
            }
        }

        // replace the property with the modified property
        if (mod) {
            this.logger.log(Logger.LOG_DEBUG, "Setting property " + osgiProp
                + " to " + prop.toString());
            props.put(osgiProp, prop.toString());
        }
    }

    /**
     * Converts an old Felix framework property into a new (standard or modified
     * Felix framework) property. If a property named <code>oldName</code> does
     * not exist in the <code>props</code> map, the map is not modified. If such
     * a property exists it is removed and add to the map with the
     * <code>newName</code> key. If both properties <code>oldName</code> and
     * <code>newName</code> exist, the property <code>newName</code> is replaced
     * with the value of the property <code>oldName</code>.
     *
     * @param props The map of properties containing the property to rename
     * @param oldName The old key of the property value
     * @param newName The new key of the property value
     */
    private void migrateProp(Map<String, String> props, String oldName,
            String newName) {
        String propValue = props.remove(oldName);
        if (propValue != null) {
            String previousNewValue = props.put(newName, propValue);
            if (previousNewValue != null) {
                logger.log(Logger.LOG_WARNING, "Old value (" + previousNewValue
                    + ") of property " + newName + " by value: " + propValue);
            } else {
                logger.log(Logger.LOG_INFO, "Property " + oldName + " ("
                    + propValue + ") renamed to " + newName);
            }
        } else {
            logger.log(Logger.LOG_DEBUG, "Property " + oldName
                + " does not exist, nothing to do");
        }
    }

    // ---------- Extension support --------------------------------------------

    /**
     * Loads additional properties into the <code>properties</code> object.
     * <p>
     * This implementation does nothing and may be overwritten by extensions
     * requiring additional properties to be set.
     * <p>
     * This method is called when the servlet is initialized to prepare the
     * configuration for <code>Felix</code>. Implementations may add
     * properties from implementation specific sources. Properties added here
     * overwrite properties loaded from the default properties file and may be
     * overwritten by parameters set in the web application.
     * <p>
     * The <code>properties</code> object has not undergone variable
     * substition and properties added by this method may also contain values
     * refererring to other properties.
     * <p>
     * The properties added in this method will not be persisted in the
     * <code>sling.properties</code> file in the <code>sling.home</code>
     * directory.
     *
     * @param properties The <code>Properties</code> object to which custom
     *            properties may be added.
     */
    protected void loadPropertiesOverride(@SuppressWarnings("unused") Map<String, String> properties) {
    }

    /**
     * Returns the <code>BundleContext</code> of the system bundle of the OSGi
     * framework launched by this servlet. This method only returns a non-<code>null</code>
     * object after the system bundle of the framework has been started and
     * before it is being stopped.
     */
    public final BundleContext getBundleContext() {
        return this.framework.getBundleContext();
    }

    // ---------- Property file support ----------------------------------------

    /**
     * Returns the abstract path name to the <code>sling.properties</code> file.
     */
    private File getSlingProperties(final String slingHome,
            final Map<String, String> properties) {
        final String prop = properties.get(SharedConstants.SLING_PROPERTIES);
        if (prop == null) {
            return new File(slingHome, CONFIG_PROPERTIES);
        }

        final File propFile = new File(prop);
        return propFile.isAbsolute() ? propFile : new File(slingHome, prop);
    }

    /**
     * Looks for <code>sling.include</code> and <code>sling.include.*</code>
     * properties in the <code>props</code> and loads properties form the
     * respective locations.
     * <p>
     * Each <code>sling.include</code> (or <code>sling.include.*</code>)
     * property may contain a comma-separated list of resource and/or file names
     * to be loaded from. The includes are loaded in alphabetical order of the
     * property names.
     * <p>
     * Each reasource path is first tried to be loaded through the
     * {@link #resourceProvider}. If that fails, the resource path is tested as
     * a file. If relative <code>slingHome</code> is used as the parent if not
     * <code>null</code>, otherwise the current working directory is used as
     * the parent.
     * <p>
     * Any non-existing resource is silently ignored.
     * <p>
     * When the method returns, the <code>sling.include</code> and
     * <code>sling.include.*</code> properties are not contained in the
     * <code>props</code> any more.
     *
     * @param props The <code>Properties</code> containing the
     *            <code>sling.include</code> and <code>sling.include.*</code>
     *            properties. This is also the destination for the new
     *            properties loaded.
     * @param slingHome The parent directory used to resolve relative path names
     *            if loading from a file. This may be <code>null</code> in
     *            which case the current working directory is used as the
     *            parent.
     */
    private void loadIncludes(Map<String, String> props, String slingHome) {
        // Build the sort map of include properties first
        // and remove include elements from the properties
        SortedMap<String, String> includes = new TreeMap<String, String>();
        for (Iterator<Entry<String, String>> pi = props.entrySet().iterator(); pi.hasNext();) {
            Entry<String, String> entry = pi.next();
            if (entry.getKey().startsWith("sling.include.")
                || entry.getKey().equals("sling.include")) {
                includes.put(entry.getKey(), entry.getValue());
                pi.remove();
            }
        }

        for (Iterator<Entry<String, String>> ii = includes.entrySet().iterator(); ii.hasNext();) {
            Map.Entry<String, String> entry = ii.next();
            String key = entry.getKey();
            String include = entry.getValue();

            // ensure variable resolution on this property
            include = Util.substVars(include, key, null, props);

            StringTokenizer tokener = new StringTokenizer(include, ",");
            while (tokener.hasMoreTokens()) {
                String file = tokener.nextToken().trim();
                InputStream is = this.resourceProvider.getResourceAsStream(file);
                try {
                    if (is == null && slingHome != null) {
                        File resFile = new File(file);
                        if (!resFile.isAbsolute()) {
                            resFile = new File(slingHome, file);
                        }
                        if (resFile.canRead()) {
                            is = new FileInputStream(resFile);
                            file = resFile.getAbsolutePath(); // for logging
                        }
                    }

                    if (is != null) {
                        this.load(props, is);
                    }
                } catch (IOException ioe) {
                    this.logger.log(Logger.LOG_ERROR,
                        "Error loading config properties from " + file, ioe);
                } finally {
                    if ( is != null ) {
                        try {
                            is.close();
                        } catch (IOException ignore) {
                        }
                    }
                }
            }
        }
    }

    /**
     * Load properties from the given resource file, which is accessed through
     * the {@link #resourceProvider}. If the resource does not exist, nothing
     * is loaded.
     *
     * @param props The <code>Properties</code> into which the loaded
     *            properties are loaded
     * @param resource The resource from which to load the resources
     */
    private void load(Map<String, String> props, String resource) {
        InputStream is = this.resourceProvider.getResourceAsStream(resource);
        if (is != null) {
            try {
                this.load(props, is);
            } catch (IOException ioe) {
                this.logger.log(Logger.LOG_ERROR,
                    "Error loading config properties from " + resource, ioe);
            } finally {
                try {
                    is.close();
                } catch (IOException ignore) {
                }
            }
        }
    }

    /**
     * Load properties from the given file. If the resource cannot be read from
     * (e.g. because it does not exist), nothing is loaded.
     *
     * @param props The <code>Properties</code> into which the loaded
     *            properties are loaded
     * @param file The <code>File</code> to load the properties from
     */
    private void load(Map<String, String> props, File file) {
        if (file != null && file.canRead()) {
            try {
                this.load(props, new FileInputStream(file));
            } catch (IOException ioe) {
                this.logger.log(Logger.LOG_ERROR,
                    "Error loading config properties from "
                        + file.getAbsolutePath(), ioe);
            }
        }
    }

    private void load(Map<String, String> props, InputStream ins)
            throws IOException {
        try {
            Properties tmp = new Properties();
            tmp.load(ins);

            for (Map.Entry<Object, Object> entry : tmp.entrySet()) {
                final String value = (String)entry.getValue();
                props.put((String) entry.getKey(), (value == null ? null : value.trim()));
            }
        } finally {
            try {
                ins.close();
            } catch (IOException ioe2) {
                // ignore
            }
        }
    }

    private void copyBootstrapCommandFile(final Map<String, String> props) {
        // check last modification date
        final URL url = this.resourceProvider.getResource(BootstrapInstaller.BOOTSTRAP_CMD_FILENAME);
        if ( url != null ) {
            this.logger.log(Logger.LOG_DEBUG, "Checking last modification date of bootstrap command file.");
            InputStream is = null;
            OutputStream os = null;
            try {
                final long lastModified = url.openConnection().getLastModified();
                final File launchpadHome = new File(props.get(SharedConstants.SLING_LAUNCHPAD));
                final File cmdFile = new File(launchpadHome, BootstrapInstaller.BOOTSTRAP_CMD_FILENAME);
                boolean copyFile = true;
                if ( cmdFile.exists() && cmdFile.lastModified() >= lastModified ) {
                    copyFile = false;
                }
                if ( copyFile ) {
                    this.logger.log(Logger.LOG_INFO, "Copying bootstrap command file.");
                    is = this.resourceProvider.getResourceAsStream(BootstrapInstaller.BOOTSTRAP_CMD_FILENAME);
                    os = new FileOutputStream(cmdFile);
                    final byte[] buffer = new byte[2048];
                    int l;
                    while ( (l = is.read(buffer, 0, buffer.length)) != -1 ) {
                        os.write(buffer, 0, l);
                    }
                }

            } catch (final IOException ioe) {
                this.logger.log(Logger.LOG_INFO, "Ignoring exception during processing of bootstrap command file.", ioe);
            } finally {
                if ( is != null ) {
                    try { is.close(); } catch (final IOException ignore) {}
                }
                if ( os != null ) {
                    try { os.close(); } catch (final IOException ignore) {}
                }
            }
        } else {
            this.logger.log(Logger.LOG_DEBUG, "Bootstrap command file not found.");
        }

    }
}
