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

org.apache.felix.main.Main Maven / Gradle / Ivy

The newest version!
/*
 * 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.felix.main;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.apache.felix.framework.util.Util;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;

/**
 * 

* This class is the default way to instantiate and execute the framework. It is not * intended to be the only way to instantiate and execute the framework; rather, it is * one example of how to do so. When embedding the framework in a host application, * this class can serve as a simple guide of how to do so. It may even be * worthwhile to reuse some of its property handling capabilities. *

**/ public class Main { /** * Switch for specifying bundle directory. **/ public static final String BUNDLE_DIR_SWITCH = "-b"; /** * 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_VALUE = "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_VALUE = "config.properties"; /** * Name of the configuration directory. */ public static final String CONFIG_DIRECTORY = "conf"; private static Framework m_fwk = null; /** *

* This method performs the main task of constructing an framework instance * and starting its execution. The following functions are performed * when invoked: *

*
    *
  1. Examine and verify command-line arguments. The launcher * accepts a "-b" command line switch to set the bundle auto-deploy * directory and a single argument to set the bundle cache directory. *
  2. *
  3. Read the system properties file. This is a file * containing properties to be pushed into System.setProperty() * before starting the framework. This mechanism is mainly shorthand * for people starting the framework from the command line to avoid having * to specify a bunch of -D system property definitions. * The only properties defined in this file that will impact the framework's * behavior are the those concerning setting HTTP proxies, such as * http.proxyHost, http.proxyPort, and * http.proxyAuth. Generally speaking, the framework does * not use system properties at all. *
  4. *
  5. Read the framework's configuration property file. This is * a file containing properties used to configure the framework * instance and to pass configuration information into * bundles installed into the framework instance. The configuration * property file is called config.properties by default * and is located in the conf/ directory of the Felix * installation directory, which is the parent directory of the * directory containing the felix.jar file. It is possible * to use a different location for the property file by specifying * the desired URL using the felix.config.properties * system property; this should be set using the -D syntax * when executing the JVM. If the config.properties file * cannot be found, then default values are used for all configuration * properties. Refer to the * Felix * constructor documentation for more information on framework * configuration properties. *
  6. *
  7. Copy configuration properties specified as system properties * into the set of configuration properties. Even though the * Felix framework does not consult system properties for configuration * information, sometimes it is convenient to specify them on the command * line when launching Felix. To make this possible, the Felix launcher * copies any configuration properties specified as system properties * into the set of configuration properties passed into Felix. *
  8. *
  9. Add shutdown hook. To make sure the framework shutdowns * cleanly, the launcher installs a shutdown hook; this can be disabled * with the felix.shutdown.hook configuration property. *
  10. *
  11. Create and initialize a framework instance. The OSGi standard * FrameworkFactory is retrieved from META-INF/services * and used to create a framework instance with the configuration properties. *
  12. *
  13. Auto-deploy bundles. All bundles in the auto-deploy * directory are deployed into the framework instance. *
  14. *
  15. Start the framework. The framework is started and * the launcher thread waits for the framework to shutdown. *
  16. *
*

* It should be noted that simply starting an instance of the framework is not * enough to create an interactive session with it. It is necessary to install * and start bundles that provide a some means to interact with the framework; * this is generally done by bundles in the auto-deploy directory or specifying * an "auto-start" property in the configuration property file. If no bundles * providing a means to interact with the framework are installed or if the * configuration property file cannot be found, the framework will appear to * be hung or deadlocked. This is not the case, it is executing correctly, * there is just no way to interact with it. *

*

* The launcher provides two ways to deploy bundles into a framework at * startup, which have associated configuration properties: *

*
    *
  • Bundle auto-deploy - Automatically deploys all bundles from a * specified directory, controlled by the following configuration * properties: *
      *
    • felix.auto.deploy.dir - Specifies the auto-deploy directory * from which bundles are automatically deploy at framework startup. * The default is the bundle/ directory of the current directory. *
    • *
    • felix.auto.deploy.action - Specifies the auto-deploy actions * to be found on bundle JAR files found in the auto-deploy directory. * The possible actions are install, update, * start, and uninstall. If no actions are specified, * then the auto-deploy directory is not processed. There is no default * value for this property. *
    • *
    *
  • *
  • Bundle auto-properties - Configuration properties which specify URLs * to bundles to install/start: *
      *
    • felix.auto.install.N - Space-delimited list of bundle * URLs to automatically install when the framework is started, * where N is the start level into which the bundle will be * installed (e.g., felix.auto.install.2). *
    • *
    • felix.auto.start.N - Space-delimited list of bundle URLs * to automatically install and start when the framework is started, * where N is the start level into which the bundle will be * installed (e.g., felix.auto.start.2). *
    • *
    *
  • *
*

* These properties should be specified in the config.properties * so that they can be processed by the launcher during the framework * startup process. *

* @param args Accepts arguments to set the auto-deploy directory and/or * the bundle cache directory. * @throws Exception If an error occurs. **/ public static void main(String[] args) throws Exception { // Look for bundle directory and/or cache directory. // We support at most one argument, which is the bundle // cache directory. String bundleDir = null; String cacheDir = null; boolean expectBundleDir = false; for (int i = 0; i < args.length; i++) { if (args[i].equals(BUNDLE_DIR_SWITCH)) { expectBundleDir = true; } else if (expectBundleDir) { bundleDir = args[i]; expectBundleDir = false; } else { cacheDir = args[i]; } } if ((args.length > 3) || (expectBundleDir && bundleDir == null)) { System.out.println("Usage: [-b ] []"); System.exit(0); } // Load system properties. Main.loadSystemProperties(); // Read configuration properties. Map configProps = Main.loadConfigProperties(); // If no configuration properties were found, then create // an empty properties object. if (configProps == null) { System.err.println("No " + CONFIG_PROPERTIES_FILE_VALUE + " found."); configProps = new HashMap(); } // Copy framework properties from the system properties. Main.copySystemProperties(configProps); // If there is a passed in bundle auto-deploy directory, then // that overwrites anything in the config file. if (bundleDir != null) { configProps.put(AutoProcessor.AUTO_DEPLOY_DIR_PROPERTY, bundleDir); } // If there is a passed in bundle cache directory, then // that overwrites anything in the config file. if (cacheDir != null) { configProps.put(Constants.FRAMEWORK_STORAGE, cacheDir); } // If enabled, register a shutdown hook to make sure the framework is // cleanly shutdown when the VM exits. String enableHook = configProps.get(SHUTDOWN_HOOK_PROP); if ((enableHook == null) || !enableHook.equalsIgnoreCase("false")) { Runtime.getRuntime().addShutdownHook(new Thread("Felix Shutdown Hook") { 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); } } }); } try { // Create an instance of the framework. FrameworkFactory factory = getFrameworkFactory(); m_fwk = factory.newFramework(configProps); // Initialize the framework, but don't start it yet. m_fwk.init(); // Use the system bundle context to process the auto-deploy // and auto-install/auto-start properties. AutoProcessor.process(configProps, m_fwk.getBundleContext()); 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); } } /** * Simple method to parse META-INF/services file for framework factory. * Currently, it assumes the first non-commented line is the class name * of the framework factory implementation. * @return The created FrameworkFactory instance. * @throws Exception if any errors occur. **/ private static FrameworkFactory getFrameworkFactory() throws Exception { URL url = Main.class.getClassLoader().getResource( "META-INF/services/org.osgi.framework.launch.FrameworkFactory"); if (url != null) { BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); try { for (String s = br.readLine(); s != null; s = br.readLine()) { s = s.trim(); // Try to load first non-empty, non-commented line. if ((s.length() > 0) && (s.charAt(0) != '#')) { return (FrameworkFactory) Class.forName(s).newInstance(); } } } finally { if (br != null) br.close(); } } throw new Exception("Could not find framework factory."); } /** *

* Loads the properties in the system property file associated with the * framework installation into System.setProperty(). These properties * are not directly used by the framework in anyway. By default, the system * property file is located in the conf/ directory of the Felix * installation directory and is called "system.properties". The * installation directory of Felix is assumed to be the parent directory of * the felix.jar file as found on the system class path property. * The precise file from which to load system properties can be set by * initializing the "felix.system.properties" system property to an * arbitrary URL. *

**/ public static void loadSystemProperties() { // 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 = null; String custom = System.getProperty(SYSTEM_PROPERTIES_PROP); if (custom != null) { try { propURL = new URL(custom); } catch (MalformedURLException ex) { System.err.print("Main: " + ex); return; } } else { // Determine where the configuration directory is by figuring // out where felix.jar is located on the system class path. File confDir = null; String classpath = System.getProperty("java.class.path"); int index = classpath.toLowerCase().indexOf("felix.jar"); int start = classpath.lastIndexOf(File.pathSeparator, index) + 1; if (index >= start) { // Get the path of the felix.jar file. String jarLocation = classpath.substring(start, index); // Calculate the conf directory based on the parent // directory of the felix.jar directory. confDir = new File( new File(new File(jarLocation).getAbsolutePath()).getParent(), CONFIG_DIRECTORY); } else { // Can't figure it out so use the current directory as default. confDir = new File(System.getProperty("user.dir"), CONFIG_DIRECTORY); } try { propURL = new File(confDir, SYSTEM_PROPERTIES_FILE_VALUE).toURL(); } catch (MalformedURLException ex) { System.err.print("Main: " + ex); return; } } // Read the properties file. Properties props = new Properties(); InputStream is = null; try { is = propURL.openConnection().getInputStream(); props.load(is); is.close(); } catch (FileNotFoundException ex) { // Ignore file not found. } catch (Exception ex) { System.err.println( "Main: Error loading system properties from " + propURL); System.err.println("Main: " + ex); try { if (is != null) is.close(); } catch (IOException ex2) { // Nothing we can do. } return; } // Perform variable substitution on specified properties. for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { String name = (String) e.nextElement(); System.setProperty(name, Util.substVars(props.getProperty(name), name, null, null)); } } /** *

* 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 conf/ directory of the Felix * installation directory and is called "config.properties". * The installation directory of Felix is assumed to be the parent * directory of the felix.jar file as found on the system class * path property. The precise file from which to load configuration * properties can be set by initializing the "felix.config.properties" * system property to an arbitrary URL. *

* @return A Properties instance or null if there was an error. **/ public static Map loadConfigProperties() { // 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. // See if the property URL was specified as a property. URL propURL = null; String custom = System.getProperty(CONFIG_PROPERTIES_PROP); if (custom != null) { try { propURL = new URL(custom); } catch (MalformedURLException ex) { System.err.print("Main: " + ex); return null; } } else { // Determine where the configuration directory is by figuring // out where felix.jar is located on the system class path. File confDir = null; String classpath = System.getProperty("java.class.path"); int index = classpath.toLowerCase().indexOf("felix.jar"); int start = classpath.lastIndexOf(File.pathSeparator, index) + 1; if (index >= start) { // Get the path of the felix.jar file. String jarLocation = classpath.substring(start, index); // Calculate the conf directory based on the parent // directory of the felix.jar directory. confDir = new File( new File(new File(jarLocation).getAbsolutePath()).getParent(), CONFIG_DIRECTORY); } else { // Can't figure it out so use the current directory as default. confDir = new File(System.getProperty("user.dir"), CONFIG_DIRECTORY); } try { propURL = new File(confDir, CONFIG_PROPERTIES_FILE_VALUE).toURL(); } catch (MalformedURLException ex) { System.err.print("Main: " + ex); return null; } } // Read the properties file. Properties props = new Properties(); InputStream is = null; try { // Try to load config.properties. is = propURL.openConnection().getInputStream(); props.load(is); is.close(); } catch (Exception ex) { // Try to close input stream if we have one. try { if (is != null) is.close(); } catch (IOException ex2) { // Nothing we can do. } return null; } // Perform variable substitution for system properties and // convert to dictionary. Map map = new HashMap(); for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { String name = (String) e.nextElement(); map.put(name, Util.substVars(props.getProperty(name), name, null, props)); } return map; } public static void copySystemProperties(Map configProps) { for (Enumeration e = System.getProperties().propertyNames(); e.hasMoreElements(); ) { String key = (String) e.nextElement(); if (key.startsWith("felix.") || key.startsWith("org.osgi.framework.")) { configProps.put(key, System.getProperty(key)); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy