public static void indexTargetPlatform( OutputStream outputStream, List<File> additionalJarFiles, long stopWaitTimeout, String... dirNames) throws Exception { Framework framework = null; Path tempPath = Files.createTempDirectory(null); ClassLoader classLoader = TargetPlatformIndexerUtil.class.getClassLoader(); try (InputStream inputStream = classLoader.getResourceAsStream("META-INF/system.packages.extra.mf")) { Map<String, String> properties = new HashMap<>(); properties.put(Constants.FRAMEWORK_STORAGE, tempPath.toString()); Manifest extraPackagesManifest = new Manifest(inputStream); Attributes attributes = extraPackagesManifest.getMainAttributes(); properties.put( Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, attributes.getValue("Export-Package")); ServiceLoader<FrameworkFactory> serviceLoader = ServiceLoader.load(FrameworkFactory.class); FrameworkFactory frameworkFactory = serviceLoader.iterator().next(); framework = frameworkFactory.newFramework(properties); framework.init(); BundleContext bundleContext = framework.getBundleContext(); Bundle systemBundle = bundleContext.getBundle(0); TargetPlatformIndexer targetPlatformIndexer = new TargetPlatformIndexer(systemBundle, additionalJarFiles, dirNames); targetPlatformIndexer.index(outputStream); } finally { framework.stop(); FrameworkEvent frameworkEvent = framework.waitForStop(stopWaitTimeout); if (frameworkEvent.getType() == FrameworkEvent.WAIT_TIMEDOUT) { throw new Exception( "OSGi framework event " + frameworkEvent + " triggered after a " + stopWaitTimeout + "ms timeout"); } PathUtil.deltree(tempPath); } }
@Override public void frameworkEvent(FrameworkEvent frameworkEvent) { if (frameworkEvent.getType() != FrameworkEvent.PACKAGES_REFRESHED) { return; } for (Bundle bundle : _startBundles) { try { startBundle(bundle, 0, false); } catch (Exception e) { _log.error(e, e); } } for (Bundle bundle : _lazyActivationBundles) { try { startBundle(bundle, Bundle.START_ACTIVATION_POLICY, false); } catch (Exception e) { _log.error(e, e); } } try { Bundle bundle = frameworkEvent.getBundle(); BundleContext bundleContext = bundle.getBundleContext(); bundleContext.removeFrameworkListener(this); } catch (Exception e) { _log.error(e, e); } }
@SuppressWarnings("rawtypes") private EventObject waitForEvent(List events, int type) throws InterruptedException { // Timeout for event delivery: 3 sec int timeout = 30; EventObject eventFound = null; while (eventFound == null && 0 < timeout) { synchronized (events) { events.wait(100); for (Object aux : events) { if (aux instanceof BundleEvent) { BundleEvent event = (BundleEvent) aux; if (type == event.getType()) { eventFound = event; break; } } else if (aux instanceof ServiceEvent) { ServiceEvent event = (ServiceEvent) aux; if (type == event.getType()) { eventFound = event; break; } } else if (aux instanceof FrameworkEvent) { FrameworkEvent event = (FrameworkEvent) aux; if (type == event.getType()) { eventFound = event; break; } } } } timeout--; } return eventFound; }
/* * Do the work that should have happened init time. This also "turns on" the * filter so future calls pass directly through this class to the wrapped * filter. */ public void frameworkEvent(FrameworkEvent event) { if (event.getType() != FrameworkEvent.STARTED) { return; } try { delayed.init(delayedConfig); ready = true; } catch (ServletException e) { log.error(e); } }
@Override public void frameworkEvent(FrameworkEvent event) { synchronized (frameworkEvents) { log.debug( "FrameworkEvent type=" + ConstantsHelper.frameworkEvent(event.getType()) + " for " + event); frameworkEvents.add(event); frameworkEvents.notifyAll(); } }
protected void assertFrameworkEvent( int type, Bundle bundle, Class<? extends Throwable> expectedThrowable) throws Exception { FrameworkEvent event = (FrameworkEvent) waitForEvent(frameworkEvents, type); log.debug("frameworkEvents=" + frameworkEvents); assertNotNull("Event not null", event); frameworkEvents.remove(event); assertEquals( ConstantsHelper.frameworkEvent(type), ConstantsHelper.frameworkEvent(event.getType())); Throwable t = event.getThrowable(); if (expectedThrowable == null) { if (t != null) { log.error("Unexpected error in Framework event: ", t); fail("Unexpected throwable: " + t); } } else { String message = expectedThrowable.getSimpleName() + " is assignable from " + t.getClass().getSimpleName(); assertTrue(message, expectedThrowable.isAssignableFrom(t.getClass())); } assertEquals(bundle, event.getSource()); assertEquals(bundle, event.getBundle()); }
public long[] getFrameworkEvents() { synchronized (frameworkEvents) { try { long[] r = new long[frameworkEvents.size() * 2]; if (bDebug) { System.out.println("server: getFrameworkEvents size=" + r.length / 2); } int i = 0; for (Iterator it = frameworkEvents.iterator(); it.hasNext(); ) { FrameworkEvent ev = (FrameworkEvent) it.next(); Bundle b = ev.getBundle(); long bid = -1; if (b == null) { if (bDebug) { System.out.println("fw event: " + ev + " - no bundle"); } } else { bid = b.getBundleId(); } r[i * 2] = bid; r[i * 2 + 1] = ev.getType(); i++; } frameworkEvents.clear(); if (bDebug) { System.out.println("server: getFrameworkEvents -> " + r); } return r; } catch (Exception e) { if (bDebug) { e.printStackTrace(); } } } return null; }
@Override public void frameworkEvent(FrameworkEvent event) { if (event.getType() == FrameworkEvent.STARTED) { fireApplicationStarted(); } }
/** * Bottom level event dispatcher for the BundleContext. * * @param originalListener listener object registered under. * @param l listener to call (may be filtered). * @param action Event class type * @param object Event object */ public void dispatchEvent(Object originalListener, Object l, int action, Object object) { // save the bundle ref to a local variable // to avoid interference from another thread closing this context AbstractBundle tmpBundle = bundle; Object previousTCCL = setContextFinder(); try { if (isValid()) /* if context still valid */ { switch (action) { case Framework.BUNDLEEVENT: case Framework.BUNDLEEVENTSYNC: { BundleListener listener = (BundleListener) l; if (Debug.DEBUG_EVENTS) { String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$ Debug.println( "dispatchBundleEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } BundleEvent event = (BundleEvent) object; switch (event.getType()) { case Framework.BATCHEVENT_BEGIN: { if (listener instanceof BatchBundleListener) ((BatchBundleListener) listener).batchBegin(); break; } case Framework.BATCHEVENT_END: { if (listener instanceof BatchBundleListener) ((BatchBundleListener) listener).batchEnd(); break; } default: { listener.bundleChanged((BundleEvent) object); } } break; } case ServiceRegistry.SERVICEEVENT: { ServiceEvent event = (ServiceEvent) object; ServiceListener listener = (ServiceListener) l; if (Debug.DEBUG_EVENTS) { String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$ Debug.println( "dispatchServiceEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } listener.serviceChanged(event); break; } case Framework.FRAMEWORKEVENT: { FrameworkListener listener = (FrameworkListener) l; if (Debug.DEBUG_EVENTS) { String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$ Debug.println( "dispatchFrameworkEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } listener.frameworkEvent((FrameworkEvent) object); break; } default: { throw new InternalError(); } } } } catch (Throwable t) { if (Debug.DEBUG_GENERAL) { Debug.println( "Exception in bottom level event dispatcher: " + t.getMessage()); // $NON-NLS-1$ Debug.printStackTrace(t); } // allow the adaptor to handle this unexpected error framework.adaptor.handleRuntimeError(t); publisherror: { if (action == Framework.FRAMEWORKEVENT) { FrameworkEvent event = (FrameworkEvent) object; if (event.getType() == FrameworkEvent.ERROR) { break publisherror; // avoid infinite loop } } framework.publishFrameworkEvent(FrameworkEvent.ERROR, tmpBundle, t); } } finally { if (previousTCCL != Boolean.FALSE) Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL); } }
/** * 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); } }