private Map loadConfigProperties()

in src/main/java/org/apache/sling/launchpad/base/impl/Sling.java [389:568]


    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.
                }
            }
        }


        Map<String, String> result = new HashMap<>();

        for (Entry<String, String> entry : runtimeProps.entrySet()) {
            result.put(entry.getKey(), entry.getValue().replace("{dollar}", "$"));
        }

        return result;
    }