Пример #1
0
  /**
   * This method performs the main task of constructing an framework instance and starting its
   * execution. The following functions are performed when invoked:
   *
   * <ol>
   *   <li><i><b>Examine and verify command-line arguments.</b></i> The launcher accepts a
   *       "<tt>-b</tt>" command line switch to set the bundle auto-deploy directory and a single
   *       argument to set the bundle cache directory.
   *   <li><i><b>Read the system properties file.</b></i> This is a file containing properties to be
   *       pushed into <tt>System.setProperty()</tt> 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 <tt>-D</tt> 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 <tt>http.proxyHost</tt>, <tt>http.proxyPort</tt>, and
   *       <tt>http.proxyAuth</tt>. Generally speaking, the framework does not use system properties
   *       at all.
   *   <li><i><b>Read the framework's configuration property file.</b></i> 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 <tt>config.properties</tt> by default and is located in the <tt>conf/</tt>
   *       directory of the Felix installation directory, which is the parent directory of the
   *       directory containing the <tt>felix.jar</tt> file. It is possible to use a different
   *       location for the property file by specifying the desired URL using the
   *       <tt>felix.config.properties</tt> system property; this should be set using the
   *       <tt>-D</tt> syntax when executing the JVM. If the <tt>config.properties</tt> file cannot
   *       be found, then default values are used for all configuration properties. Refer to the <a
   *       href="Felix.html#Felix(java.util.Map)"><tt>Felix</tt></a> constructor documentation for
   *       more information on framework configuration properties.
   *   <li><i><b>Copy configuration properties specified as system properties into the set of
   *       configuration properties.</b></i> 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.
   *   <li><i><b>Add shutdown hook.</b></i> To make sure the framework shutdowns cleanly, the
   *       launcher installs a shutdown hook; this can be disabled with the
   *       <tt>felix.shutdown.hook</tt> configuration property.
   *   <li><i><b>Create and initialize a framework instance.</b></i> The OSGi standard
   *       <tt>FrameworkFactory</tt> is retrieved from <tt>META-INF/services</tt> and used to create
   *       a framework instance with the configuration properties.
   *   <li><i><b>Auto-deploy bundles.</b></i> All bundles in the auto-deploy directory are deployed
   *       into the framework instance.
   *   <li><i><b>Start the framework.</b></i> The framework is started and the launcher thread waits
   *       for the framework to shutdown.
   * </ol>
   *
   * <p>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.
   *
   * <p>The launcher provides two ways to deploy bundles into a framework at startup, which have
   * associated configuration properties:
   *
   * <ul>
   *   <li>Bundle auto-deploy - Automatically deploys all bundles from a specified directory,
   *       controlled by the following configuration properties:
   *       <ul>
   *         <li><tt>felix.auto.deploy.dir</tt> - Specifies the auto-deploy directory from which
   *             bundles are automatically deploy at framework startup. The default is the
   *             <tt>bundle/</tt> directory of the current directory.
   *         <li><tt>felix.auto.deploy.action</tt> - Specifies the auto-deploy actions to be found
   *             on bundle JAR files found in the auto-deploy directory. The possible actions are
   *             <tt>install</tt>, <tt>update</tt>, <tt>start</tt>, and <tt>uninstall</tt>. If no
   *             actions are specified, then the auto-deploy directory is not processed. There is no
   *             default value for this property.
   *       </ul>
   *   <li>Bundle auto-properties - Configuration properties which specify URLs to bundles to
   *       install/start:
   *       <ul>
   *         <li><tt>felix.auto.install.N</tt> - Space-delimited list of bundle URLs to
   *             automatically install when the framework is started, where <tt>N</tt> is the start
   *             level into which the bundle will be installed (e.g., felix.auto.install.2).
   *         <li><tt>felix.auto.start.N</tt> - Space-delimited list of bundle URLs to automatically
   *             install and start when the framework is started, where <tt>N</tt> is the start
   *             level into which the bundle will be installed (e.g., felix.auto.start.2).
   *       </ul>
   * </ul>
   *
   * <p>These properties should be specified in the <tt>config.properties</tt> 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 <bundle-deploy-dir>] [<bundle-cache-dir>]");
      System.exit(0);
    }

    // Load system properties.
    Main.loadSystemProperties();

    // Read configuration properties.
    Properties 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 Properties();
    }

    // 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.setProperty(AutoProcessor.AUTO_DEPLOY_DIR_PROPERY, bundleDir);
    }

    // If there is a passed in bundle cache directory, then
    // that overwrites anything in the config file.
    if (cacheDir != null) {
      configProps.setProperty(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.getProperty(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);
    }
  }