All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.drombler.acp.startup.main.impl.Main Maven / Gradle / Ivy

/*
 *         COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Notice
 *
 * The contents of this file are subject to the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.opensource.org/licenses/cddl1.txt
 *
 * The Original Code is Drombler.org. The Initial Developer of the
 * Original Code is Florian Brunner (Sourceforge.net user: puce).
 * Copyright 2012 Drombler.org. All Rights Reserved.
 *
 * Contributor(s): .
 */
package org.drombler.acp.startup.main.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import org.apache.felix.framework.util.Util;
import org.drombler.acp.startup.main.ApplicationConfigProvider;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;

public class Main {

//    private static final Logger LOG = LoggerFactory.getLogger(Main.class); // TODO: outside OSGi Framework...?
    public static final String USER_DIR_PROPERTY = "platform.userdir";

    /**
     * The property name used to specify whether the launcher should install a shutdown hook.
     *
     */
    public static final String SHUTDOWN_HOOK_PROP = "felix.shutdown.hook";
    /**
     * The property name used to specify an URL to the system property file.
     *
     */
    public static final String SYSTEM_PROPERTIES_PROP = "felix.system.properties";
    /**
     * The default name used for the system properties file.
     *
     */
    public static final String SYSTEM_PROPERTIES_FILE_NAME = "system.properties";
    /**
     * The property name used to specify an URL to the configuration property file to be used for the created the
     * framework instance.
     *
     */
    public static final String CONFIG_PROPERTIES_PROP = "felix.config.properties";
    /**
     * The default name used for the configuration properties file.
     *
     */
    public static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
    /**
     * Name of the configuration directory.
     */
    public static final String CONFIG_DIRECTORY = "conf";
    /**
     * The jar URI prefix "jar:"
     */
    private static final String FULL_JAR_URI_PREFIX = "jar:";
    /**
     * Length of the jar URI prefix "jar:"
     */
    private static final int FULL_JAR_URI_PREFIX_LENGTH = 4;
    private static final ServiceLoader frameworkFactoryLoader = ServiceLoader.load(
            FrameworkFactory.class);
    private static Framework m_fwk = null;

    public static void main(String[] args) throws Exception {
        CommandLineArgs commandLineArgs = CommandLineArgs.parseCommandLineArgs(args);
        Main main = new Main();
        main.start(commandLineArgs);
    }

    public void start(CommandLineArgs commandLineArgs) throws URISyntaxException, MalformedURLException, IOException,
            MissingPropertyException {
        Path installDirPath = getInstallDirPath();

        loadSystemProperties(installDirPath);

        Properties defaultConfigProps = getDefaultConfigProps();
        Properties installConfigProps = new Properties(defaultConfigProps);
        loadConfigProperties(installConfigProps, installDirPath);
        overrideInstallConfigProps(installConfigProps, commandLineArgs);

        Path userDirPath = getUserDirPath(installConfigProps);
        if (!Files.exists(userDirPath)) {
            Files.createDirectories(userDirPath);
        }
        System.out.println("User dir: " + userDirPath);
        Properties userConfigProps = new Properties(installConfigProps);
        loadConfigProperties(userConfigProps, userDirPath);

        resolveProperties(userConfigProps);
        copySystemProperties(userConfigProps);

        registerShutdownHook(userConfigProps);

        try {
            // Create an instance of the framework.
            FrameworkFactory factory = getFrameworkFactory();
            Map configMap = new HashMap<>(userConfigProps.size());
            for (String propertyName : userConfigProps.stringPropertyNames()) {
                configMap.put(propertyName, userConfigProps.getProperty(propertyName));
            }
            m_fwk = factory.newFramework(configMap);
            // Initialize the framework, but don't start it yet.
            m_fwk.init();
            initServices();
            // Use the system bundle context to process the auto-deploy
            // and auto-install/auto-start properties.
            AutoProcessor autoProcessor = new AutoProcessor();
            autoProcessor.process(m_fwk, configMap, installDirPath, userDirPath);
            FrameworkEvent event;
            do {
                // Start the framework.
                m_fwk.start();
                // Wait for framework to stop to exit the VM.
                event = m_fwk.waitForStop(0);
            } // If the framework was updated, then restart it.
            while (event.getType() == FrameworkEvent.STOPPED_UPDATE);
            // Otherwise, exit.
            System.exit(0);
        } catch (Exception ex) {
            System.err.println("Could not create framework: " + ex);
            ex.printStackTrace();
            System.exit(0);
        }
    }

    private void registerShutdownHook(Properties userConfigProps) {
        // If enabled, register a shutdown hook to make sure the framework is
        // cleanly shutdown when the VM exits.
        String enableHook = userConfigProps.getProperty(SHUTDOWN_HOOK_PROP);
        if ((enableHook == null) || !enableHook.equalsIgnoreCase("false")) {
            Runtime.getRuntime().addShutdownHook(new Thread("Felix Shutdown Hook") {

                @Override
                public void run() {
                    try {
                        if (m_fwk != null) {
                            m_fwk.stop();
                            m_fwk.waitForStop(0);
                        }
                    } catch (Exception ex) {
                        System.err.println("Error stopping framework: " + ex);
                    }
                }
            });
        }
    }

    private void resolveProperties(Properties configProps) throws IllegalArgumentException {
        for (String propertyName : configProps.stringPropertyNames()) {
            configProps.setProperty(propertyName,
                    Util.substVars(configProps.getProperty(propertyName), propertyName, null, configProps));
        }
    }

    private void overrideInstallConfigProps(Properties installConfigProps, CommandLineArgs commandLineArgs) {
        if (commandLineArgs.getUserDir() != null) {
            installConfigProps.setProperty(USER_DIR_PROPERTY, commandLineArgs.getUserDir());
        }
    }

    private Path getUserDirPath(Properties installConfigProps) throws MissingPropertyException {
        String userDirName = installConfigProps.getProperty(USER_DIR_PROPERTY);
        if (userDirName == null) {
            throw new MissingPropertyException("Undefined property: " + USER_DIR_PROPERTY);
        }
        return Paths.get(userDirName);
    }

    private FrameworkFactory getFrameworkFactory() throws Exception {
        for (FrameworkFactory frameworkFactory : frameworkFactoryLoader) {
            return frameworkFactory;
        }

        throw new Exception("Could not find framework factory.");
    }

    protected void loadSystemProperties(Path rootDirPath) throws MalformedURLException, IOException {
        Properties props = new Properties();
        loadProperties(props, SYSTEM_PROPERTIES_PROP, rootDirPath, SYSTEM_PROPERTIES_FILE_NAME);

        for (String propertyName : props.stringPropertyNames()) {
            System.setProperty(propertyName, Util.substVars(props.getProperty(propertyName), propertyName, null, null));
        }

    }

    private void loadProperties(Properties props, String systemPropertyName, Path rootDirPath, String propertiesFileName)
            throws IOException, MalformedURLException {
        String custom = System.getProperty(systemPropertyName);
        URL propURL = custom != null ? new URL(custom) : rootDirPath.resolve(CONFIG_DIRECTORY).resolve(
                propertiesFileName).toUri().toURL();

        try (InputStream is = propURL.openConnection().getInputStream()) {
            props.load(is);
        } catch (FileNotFoundException ex) {
            // Ignore file not found.
        } catch (IOException ex) {
            System.err.println(
                    "Main: Error loading system properties from " + propURL);
            throw ex;
        }
    }

    private void loadConfigProperties(Properties configProps, Path rootDirPath) throws MalformedURLException,
            IOException {
        loadProperties(configProps, CONFIG_PROPERTIES_PROP, rootDirPath, CONFIG_PROPERTIES_FILE_NAME);
    }

    private void copySystemProperties(Properties configProps) {
        System.getProperties().stringPropertyNames().stream().
                filter((propertyName)
                        -> (propertyName.startsWith("felix.") || propertyName.startsWith("org.osgi.framework."))).
                forEach((propertyName) -> configProps.setProperty(propertyName, System.getProperty(propertyName)));
    }

    private Path getInstallDirPath() throws URISyntaxException {
        Class
type = Main.class; String jarResourceURIString = type.getResource("/" + type.getName().replace(".", "/") + ".class").toURI(). toString(); int endOfJarPathIndex = jarResourceURIString.indexOf("!/"); String mainJarURIString = endOfJarPathIndex >= 0 ? jarResourceURIString.substring(0, endOfJarPathIndex) : jarResourceURIString; if (mainJarURIString.startsWith(FULL_JAR_URI_PREFIX)) { mainJarURIString = mainJarURIString.substring(FULL_JAR_URI_PREFIX_LENGTH); } Path mainJarPath = Paths.get(URI.create(mainJarURIString)); // /bin/.jar return mainJarPath.getParent().getParent(); } protected Properties getDefaultConfigProps() throws IOException { Properties props = new Properties(); try (InputStream is = Main.class.getResourceAsStream("config.properties")) { props.load(is); } return props; } private void initServices() throws IOException { m_fwk.getBundleContext().registerService(ApplicationConfigProvider.class, new ApplicationConfigProviderImpl(), null); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy