1 /******************************************************************************* 2 * Copyright (c) 2000, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Julian Chen - fix for bug #92572, jclRM 14 * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - fix for bug 265532 15 * Christoph Läubrich - remove InternalPlatform.getDefault().log (bug 55083) 16 *******************************************************************************/ 17 package org.eclipse.core.internal.runtime; 18 19 import java.io.File; 20 import java.net.URL; 21 import java.util.*; 22 import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences; 23 import org.eclipse.core.internal.preferences.exchange.IProductPreferencesService; 24 import org.eclipse.core.internal.preferences.legacy.InitLegacyPreferences; 25 import org.eclipse.core.internal.preferences.legacy.ProductPreferencesService; 26 import org.eclipse.core.runtime.*; 27 import org.eclipse.core.runtime.content.IContentTypeManager; 28 import org.eclipse.core.runtime.preferences.IPreferencesService; 29 import org.eclipse.equinox.app.IApplicationContext; 30 import org.eclipse.equinox.internal.app.*; 31 import org.eclipse.equinox.internal.app.Activator; 32 import org.eclipse.equinox.log.*; 33 import org.eclipse.osgi.container.ModuleContainer; 34 import org.eclipse.osgi.framework.log.FrameworkLog; 35 import org.eclipse.osgi.service.datalocation.Location; 36 import org.eclipse.osgi.service.debug.DebugOptions; 37 import org.eclipse.osgi.service.environment.EnvironmentInfo; 38 import org.eclipse.osgi.service.resolver.PlatformAdmin; 39 import org.osgi.framework.*; 40 import org.osgi.framework.namespace.HostNamespace; 41 import org.osgi.framework.namespace.IdentityNamespace; 42 import org.osgi.framework.wiring.*; 43 import org.osgi.resource.Namespace; 44 import org.osgi.util.tracker.ServiceTracker; 45 46 /** 47 * Bootstrap class for the platform. It is responsible for setting up the 48 * platform class loader and passing control to the actual application class 49 */ 50 public final class InternalPlatform { 51 52 private static final String[] ARCH_LIST = { Platform.ARCH_X86, Platform.ARCH_X86_64 }; 53 54 // debug support: set in loadOptions() 55 public static boolean DEBUG = false; 56 public static boolean DEBUG_PLUGIN_PREFERENCES = false; 57 58 private boolean splashEnded = false; 59 private boolean initialized; 60 private static final String KEYRING = "-keyring"; //$NON-NLS-1$ 61 private String keyringFile; 62 63 //XXX This is not synchronized 64 private Map<Bundle,Log> logs = new HashMap<>(5); 65 66 private static final String[] OS_LIST = { Platform.OS_FREEBSD, Platform.OS_LINUX, Platform.OS_MACOSX, Platform.OS_WIN32 }; 67 private String password = ""; //$NON-NLS-1$ 68 private static final String PASSWORD = "-password"; //$NON-NLS-1$ 69 70 public static final String PROP_APPLICATION = "eclipse.application"; //$NON-NLS-1$ 71 public static final String PROP_ARCH = "osgi.arch"; //$NON-NLS-1$ 72 public static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$ 73 public static final String PROP_CONSOLE_LOG = "eclipse.consoleLog"; //$NON-NLS-1$ 74 public static final String PROP_DEBUG = "osgi.debug"; //$NON-NLS-1$ 75 public static final String PROP_DEV = "osgi.dev"; //$NON-NLS-1$ 76 77 // OSGI system properties. Copied from EclipseStarter 78 public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$ 79 public static final String PROP_NL = "osgi.nl"; //$NON-NLS-1$ 80 public static final String PROP_OS = "osgi.os"; //$NON-NLS-1$ 81 82 // Eclipse System Properties 83 public static final String PROP_PRODUCT = "eclipse.product"; //$NON-NLS-1$ 84 public static final String PROP_WS = "osgi.ws"; //$NON-NLS-1$ 85 public static final String PROP_ACTIVATE_PLUGINS = "eclipse.activateRuntimePlugins"; //$NON-NLS-1$ 86 87 private static final InternalPlatform singleton = new InternalPlatform(); 88 89 private static final String[] WS_LIST = { Platform.WS_COCOA, Platform.WS_GTK, Platform.WS_WIN32, Platform.WS_WPF }; 90 private Path cachedInstanceLocation; // Cache the path of the instance location 91 private ServiceTracker<Location,Location> configurationLocation = null; 92 private BundleContext context; 93 private FrameworkWiring fwkWiring; 94 95 private Map<IBundleGroupProvider,ServiceRegistration<IBundleGroupProvider>> groupProviders = new HashMap<>(3); 96 private ServiceTracker<Location,Location> installLocation = null; 97 private ServiceTracker<Location,Location> instanceLocation = null; 98 private ServiceTracker<Location,Location> userLocation = null; 99 100 private Plugin runtimeInstance; // Keep track of the plugin object for runtime in case the backward compatibility is run. 101 102 private ServiceRegistration<ILegacyPreferences> legacyPreferencesService = null; 103 private ServiceRegistration<IProductPreferencesService> customPreferencesService = null; 104 105 private ServiceTracker<EnvironmentInfo,EnvironmentInfo> environmentTracker = null; 106 private ServiceTracker<FrameworkLog,FrameworkLog> logTracker = null; 107 private ServiceTracker<PlatformAdmin, PlatformAdmin> platformTracker = null; 108 private ServiceTracker<DebugOptions,DebugOptions> debugTracker = null; 109 private ServiceTracker<IContentTypeManager,IContentTypeManager> contentTracker = null; 110 private ServiceTracker<IPreferencesService,IPreferencesService> preferencesTracker = null; 111 private ServiceTracker<IBundleGroupProvider,IBundleGroupProvider> groupProviderTracker = null; 112 private ServiceTracker<ExtendedLogReaderService,ExtendedLogReaderService> logReaderTracker = null; 113 private ServiceTracker<ExtendedLogService,ExtendedLogService> extendedLogTracker = null; 114 115 private IProduct product; 116 getDefault()117 public static InternalPlatform getDefault() { 118 return singleton; 119 } 120 121 /** 122 * Private constructor to block instance creation. 123 */ InternalPlatform()124 private InternalPlatform() { 125 super(); 126 } 127 128 /** 129 * @see Platform#addLogListener(ILogListener) 130 */ addLogListener(ILogListener listener)131 public void addLogListener(ILogListener listener) { 132 assertInitialized(); 133 RuntimeLog.addLogListener(listener); 134 } 135 assertInitialized()136 private void assertInitialized() { 137 //avoid the Policy.bind if assertion is true 138 if (!initialized) 139 Assert.isTrue(false, Messages.meta_appNotInit); 140 } 141 142 /** 143 * @see Platform#endSplash() 144 */ endSplash()145 public void endSplash() { 146 synchronized (this) { 147 if (splashEnded) 148 return; // do not do this more than once 149 splashEnded = true; 150 } 151 IApplicationContext applicationContext = getApplicationContext(); 152 if (applicationContext != null) 153 applicationContext.applicationRunning(); 154 } 155 156 /** 157 * @see Platform#getAdapterManager() 158 */ getAdapterManager()159 public IAdapterManager getAdapterManager() { 160 assertInitialized(); 161 return AdapterManager.getDefault(); 162 } 163 164 /** 165 * XXX Use the Environment info service. Need to see how to set the value of the app args. 166 */ getApplicationArgs()167 public String[] getApplicationArgs() { 168 return CommandLineArgs.getApplicationArgs(); 169 } 170 getBooleanOption(String option, boolean defaultValue)171 public boolean getBooleanOption(String option, boolean defaultValue) { 172 String value = getOption(option); 173 if (value == null) 174 return defaultValue; 175 return "true".equalsIgnoreCase(value); //$NON-NLS-1$ 176 } 177 getBundleContext()178 public BundleContext getBundleContext() { 179 return context; 180 } 181 182 /** 183 * Returns the bundle id of the bundle that contains the provided object, or 184 * <code>null</code> if the bundle could not be determined. 185 */ getBundleId(Object object)186 public String getBundleId(Object object) { 187 if (object == null) 188 return null; 189 Bundle source = FrameworkUtil.getBundle(object.getClass()); 190 if (source != null && source.getSymbolicName() != null) 191 return source.getSymbolicName(); 192 193 return null; 194 } 195 getBundleGroupProviders()196 public IBundleGroupProvider[] getBundleGroupProviders() { 197 return groupProviderTracker.getServices(new IBundleGroupProvider[0]); 198 } 199 registerBundleGroupProvider(IBundleGroupProvider provider)200 public void registerBundleGroupProvider(IBundleGroupProvider provider) { 201 // get the bundle context and register the provider as a service 202 ServiceRegistration<IBundleGroupProvider> registration = getBundleContext().registerService(IBundleGroupProvider.class, provider, null); 203 // store the service registration (map provider -> registration) 204 synchronized (groupProviders) { 205 groupProviders.put(provider, registration); 206 } 207 } 208 unregisterBundleGroupProvider(IBundleGroupProvider provider)209 public void unregisterBundleGroupProvider(IBundleGroupProvider provider) { 210 // get the service reference (map provider -> reference) 211 ServiceRegistration<IBundleGroupProvider> registration; 212 synchronized (groupProviders) { 213 registration = groupProviders.remove(provider); 214 } 215 if (registration == null) 216 return; 217 // unregister the provider 218 registration.unregister(); 219 } 220 getBundle(String symbolicName)221 public Bundle getBundle(String symbolicName) { 222 Bundle[] bundles = getBundles(symbolicName, null); 223 return bundles != null && bundles.length > 0 ? bundles[0] : null; 224 } 225 getBundles(String symbolicName, String versionRange)226 public Bundle[] getBundles(String symbolicName, String versionRange) { 227 if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) { 228 symbolicName = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getSymbolicName(); 229 } 230 Map<String, String> directives = Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, 231 getRequirementFilter(symbolicName, versionRange)); 232 Collection<BundleCapability> matchingBundleCapabilities = fwkWiring.findProviders(ModuleContainer 233 .createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, directives, Collections.emptyMap())); 234 235 if (matchingBundleCapabilities.isEmpty()) { 236 return null; 237 } 238 239 Bundle[] results = matchingBundleCapabilities.stream().map(c -> c.getRevision().getBundle()) 240 // Remove all the bundles that are installed or uninstalled 241 .filter(bundle -> (bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) 242 .sorted((b1, b2) -> b2.getVersion().compareTo(b1.getVersion())) // highest version first 243 .toArray(Bundle[]::new); 244 245 return results.length > 0 ? results : null; 246 } 247 getRequirementFilter(String symbolicName, String versionRange)248 private String getRequirementFilter(String symbolicName, String versionRange) { 249 VersionRange range = versionRange == null ? null : new VersionRange(versionRange); 250 StringBuilder filter = new StringBuilder(); 251 if (range != null) { 252 filter.append("(&"); //$NON-NLS-1$ 253 } 254 filter.append('(').append(IdentityNamespace.IDENTITY_NAMESPACE).append('=').append(symbolicName).append(')'); 255 256 if (range != null) { 257 filter.append(range.toFilterString(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE)).append(')'); 258 } 259 return filter.toString(); 260 } 261 getCommandLineArgs()262 public String[] getCommandLineArgs() { 263 return CommandLineArgs.getAllArgs(); 264 } 265 getConfigurationLocation()266 public Location getConfigurationLocation() { 267 assertInitialized(); 268 return configurationLocation.getService(); 269 } 270 271 /** 272 * Lazy initialize ContentTypeManager - it can only be used after the registry is up and running 273 */ getContentTypeManager()274 public IContentTypeManager getContentTypeManager() { 275 return contentTracker == null ? null : contentTracker.getService(); 276 } 277 getEnvironmentInfoService()278 public EnvironmentInfo getEnvironmentInfoService() { 279 return environmentTracker == null ? null : environmentTracker.getService(); 280 } 281 getFrameworkLog()282 public FrameworkLog getFrameworkLog() { 283 return logTracker == null ? null : logTracker.getService(); 284 } 285 getFragments(Bundle bundle)286 public Bundle[] getFragments(Bundle bundle) { 287 BundleWiring wiring = bundle.adapt(BundleWiring.class); 288 if (wiring == null) { 289 return null; 290 } 291 List<BundleWire> hostWires = wiring.getProvidedWires(HostNamespace.HOST_NAMESPACE); 292 if (hostWires == null) { 293 // we don't hold locks while checking the graph, just return if no longer valid 294 return null; 295 } 296 Bundle[] result = hostWires.stream().map(wire -> wire.getRequirer().getBundle()).filter(Objects::nonNull) 297 .toArray(Bundle[]::new); 298 return result.length > 0 ? result : null; 299 } 300 getHosts(Bundle bundle)301 public Bundle[] getHosts(Bundle bundle) { 302 BundleWiring wiring = bundle.adapt(BundleWiring.class); 303 if (wiring == null) { 304 return null; 305 } 306 List<BundleWire> hostWires = wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE); 307 if (hostWires == null) { 308 // we don't hold locks while checking the graph, just return if no longer valid 309 return null; 310 } 311 Bundle[] result = hostWires.stream().map(wire -> wire.getProvider().getBundle()).filter(Objects::nonNull) 312 .toArray(Bundle[]::new); 313 return result.length > 0 ? result : null; 314 } 315 getInstallLocation()316 public Location getInstallLocation() { 317 assertInitialized(); 318 return installLocation.getService(); 319 } 320 getInstallURL()321 public URL getInstallURL() { 322 Location location = getInstallLocation(); 323 // it is pretty much impossible for the install location to be null. If it is, the 324 // system is in a bad way so throw and exception and get the heck outta here. 325 if (location == null) 326 throw new IllegalStateException("The installation location must not be null"); //$NON-NLS-1$ 327 return location.getURL(); 328 } 329 getInstanceLocation()330 public Location getInstanceLocation() { 331 assertInitialized(); 332 return instanceLocation.getService(); 333 } 334 335 /** 336 * @see Platform#getLocation() 337 */ getLocation()338 public IPath getLocation() throws IllegalStateException { 339 if (cachedInstanceLocation == null) { 340 Location location = getInstanceLocation(); 341 if (location == null) 342 return null; 343 // This makes the assumption that the instance location is a file: URL 344 File file = new File(location.getURL().getFile()); 345 cachedInstanceLocation = new Path(file.toString()); 346 } 347 return cachedInstanceLocation; 348 } 349 350 /** 351 * Returns a log for the given plugin. Creates a new one if needed. 352 * XXX change this into a LogMgr service that would keep track of the map. See if it can be a service factory. 353 * It would contain all the logging methods that are here. 354 * Relate to RuntimeLog if appropriate. 355 * The system log listener needs to be optional: turned on or off. What about a system property? :-) 356 */ getLog(Bundle bundle)357 public ILog getLog(Bundle bundle) { 358 Log result = logs.get(bundle); 359 if (result != null) 360 return result; 361 ExtendedLogService logService = extendedLogTracker.getService(); 362 Logger logger = logService != null ? logService.getLogger(bundle, PlatformLogWriter.EQUINOX_LOGGER_NAME) : null; 363 result = new Log(bundle, logger); 364 ExtendedLogReaderService logReader = logReaderTracker.getService(); 365 logReader.addLogListener(result, result); 366 logs.put(bundle, result); 367 return result; 368 } 369 getNL()370 public String getNL() { 371 return getBundleContext().getProperty(PROP_NL); 372 } 373 374 /** 375 * Unicode locale extensions are defined using command line parameter -nlExtensions, 376 * or the system property "osgi.nl.extensions". 377 */ getNLExtensions()378 public String getNLExtensions() { 379 String nlExtensions = PlatformActivator.getContext().getProperty("osgi.nl.extensions"); //$NON-NLS-1$ 380 if (nlExtensions == null) 381 return ""; //$NON-NLS-1$ 382 if (!nlExtensions.startsWith("@")) //$NON-NLS-1$ 383 nlExtensions = '@' + nlExtensions; 384 return nlExtensions; 385 } 386 387 /** 388 * @see Platform 389 */ getOption(String option)390 public String getOption(String option) { 391 DebugOptions options = getDebugOptions(); 392 if (options != null) 393 return options.getOption(option); 394 return null; 395 } 396 getOS()397 public String getOS() { 398 return getBundleContext().getProperty(PROP_OS); 399 } 400 getOSArch()401 public String getOSArch() { 402 return getBundleContext().getProperty(PROP_ARCH); 403 } 404 getPlatformAdmin()405 public PlatformAdmin getPlatformAdmin() { 406 return platformTracker == null ? null : platformTracker.getService(); 407 } 408 409 getPreferencesService()410 public IPreferencesService getPreferencesService() { 411 return preferencesTracker == null ? null : preferencesTracker.getService(); 412 } 413 414 /* 415 * XXX move this into the app model. 416 */ getProduct()417 public IProduct getProduct() { 418 if (product != null) 419 return product; 420 EclipseAppContainer container = Activator.getContainer(); 421 IBranding branding = container == null ? null : container.getBranding(); 422 if (branding == null) 423 return null; 424 Object brandingProduct = branding.getProduct(); 425 if (!(brandingProduct instanceof IProduct)) 426 brandingProduct = new Product(branding); 427 product = (IProduct) brandingProduct; 428 return product; 429 } 430 getRegistry()431 public IExtensionRegistry getRegistry() { 432 return RegistryFactory.getRegistry(); 433 } 434 435 /** 436 * XXX deprecate and use NLS or BundleFinder.find() 437 */ getResourceBundle(Bundle bundle)438 public ResourceBundle getResourceBundle(Bundle bundle) { 439 return ResourceTranslator.getResourceBundle(bundle); 440 } 441 442 /** 443 * XXX deprecate and use NLS or BundleFinder.find() 444 */ getResourceString(Bundle bundle, String value)445 public String getResourceString(Bundle bundle, String value) { 446 return ResourceTranslator.getResourceString(bundle, value); 447 } 448 449 /** 450 * XXX deprecate and use NLS or BundleFinder.find() 451 */ getResourceString(Bundle bundle, String value, ResourceBundle resourceBundle)452 public String getResourceString(Bundle bundle, String value, ResourceBundle resourceBundle) { 453 return ResourceTranslator.getResourceString(bundle, value, resourceBundle); 454 } 455 456 /** 457 * This method is only used to register runtime once compatibility has been started. 458 */ getRuntimeInstance()459 public Plugin getRuntimeInstance() { 460 return runtimeInstance; 461 } 462 getApplicationContext()463 private IApplicationContext getApplicationContext() { 464 Collection<ServiceReference<IApplicationContext>> references; 465 try { 466 references = context.getServiceReferences(IApplicationContext.class, "(eclipse.application.type=main.thread)"); //$NON-NLS-1$ 467 } catch (InvalidSyntaxException e) { 468 return null; 469 } 470 if (references == null || references.isEmpty()) 471 return null; 472 // assumes the application context is available as a service 473 ServiceReference<IApplicationContext> firstRef = references.iterator().next(); 474 IApplicationContext result = context.getService(firstRef); 475 if (result != null) { 476 context.ungetService(firstRef); 477 return result; 478 } 479 return null; 480 } 481 482 /** 483 * XXX Investigate the usage of a service factory 484 */ getStateLocation(Bundle bundle)485 public IPath getStateLocation(Bundle bundle) { 486 return getStateLocation(bundle, true); 487 } 488 getStateLocation(Bundle bundle, boolean create)489 public IPath getStateLocation(Bundle bundle, boolean create) throws IllegalStateException { 490 assertInitialized(); 491 IPath result = MetaDataKeeper.getMetaArea().getStateLocation(bundle); 492 if (create) 493 result.toFile().mkdirs(); 494 return result; 495 } 496 getStateTimeStamp()497 public long getStateTimeStamp() { 498 PlatformAdmin admin = getPlatformAdmin(); 499 return admin == null ? -1 : admin.getState(false).getTimeStamp(); 500 } 501 getUserLocation()502 public Location getUserLocation() { 503 assertInitialized(); 504 return userLocation.getService(); 505 } 506 getWS()507 public String getWS() { 508 return getBundleContext().getProperty(PROP_WS); 509 } 510 initializeAuthorizationHandler()511 private void initializeAuthorizationHandler() { 512 try { 513 AuthorizationHandler.setKeyringFile(keyringFile); 514 AuthorizationHandler.setPassword(password); 515 } catch (NoClassDefFoundError e) { 516 // The authorization fragment is not available. If someone tries to use that API, an error will be logged 517 } 518 } 519 520 /* 521 * Finds and loads the options file 522 */ initializeDebugFlags()523 void initializeDebugFlags() { 524 // load runtime options 525 DEBUG = getBooleanOption(Platform.PI_RUNTIME + "/debug", false); //$NON-NLS-1$ 526 if (DEBUG) { 527 DEBUG_PLUGIN_PREFERENCES = getBooleanOption(Platform.PI_RUNTIME + "/preferences/plugin", false); //$NON-NLS-1$ 528 } 529 } 530 isFragment(Bundle bundle)531 public boolean isFragment(Bundle bundle) { 532 BundleRevisions bundleRevisions = bundle.adapt(BundleRevisions.class); 533 List<BundleRevision> revisions = bundleRevisions.getRevisions(); 534 if (revisions.isEmpty()) { 535 // bundle is uninstalled and not current users; just return false 536 return false; 537 } 538 return (revisions.get(0).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0; 539 } 540 541 /* 542 *XXX do what you want to do. track osgi, track runtime, or whatever. 543 */ isRunning()544 public boolean isRunning() { 545 try { 546 return initialized && context != null && context.getBundle().getState() == Bundle.ACTIVE; 547 } catch (IllegalStateException e) { 548 return false; 549 } 550 } 551 552 /** 553 * Returns a list of known system architectures. 554 * 555 * @return the list of system architectures known to the system 556 * XXX This is useless 557 */ knownOSArchValues()558 public String[] knownOSArchValues() { 559 return ARCH_LIST; 560 } 561 562 /** 563 * Returns a list of known operating system names. 564 * 565 * @return the list of operating systems known to the system 566 * XXX This is useless 567 */ knownOSValues()568 public String[] knownOSValues() { 569 return OS_LIST; 570 } 571 572 /** 573 * Returns a list of known windowing system names. 574 * 575 * @return the list of window systems known to the system 576 * XXX This is useless 577 */ knownWSValues()578 public String[] knownWSValues() { 579 return WS_LIST; 580 } 581 processCommandLine(String[] args)582 private void processCommandLine(String[] args) { 583 if (args == null || args.length == 0) 584 return; 585 586 for (int i = 0; i < args.length; i++) { 587 // check for args with parameters 588 if (i == args.length - 1 || args[i + 1].startsWith("-")) //$NON-NLS-1$ 589 continue; 590 String arg = args[++i]; 591 592 // look for the keyring file 593 if (args[i - 1].equalsIgnoreCase(KEYRING)) 594 keyringFile = arg; 595 // look for the user password. 596 if (args[i - 1].equalsIgnoreCase(PASSWORD)) 597 password = arg; 598 } 599 } 600 601 /** 602 * @see Platform#removeLogListener(ILogListener) 603 */ removeLogListener(ILogListener listener)604 public void removeLogListener(ILogListener listener) { 605 assertInitialized(); 606 RuntimeLog.removeLogListener(listener); 607 } 608 609 /** 610 * This method is only used to register runtime once compatibility has been started. 611 */ setRuntimeInstance(Plugin runtime)612 public void setRuntimeInstance(Plugin runtime) { 613 runtimeInstance = runtime; 614 } 615 616 /** 617 * Internal method for starting up the platform. The platform is not started with any location 618 * and should not try to access the instance data area. 619 * 620 * Note: the content type manager must be initialized only after the registry has been created 621 */ start(BundleContext runtimeContext)622 public void start(BundleContext runtimeContext) { 623 this.context = runtimeContext; 624 this.fwkWiring = runtimeContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class); 625 openOSGiTrackers(); 626 splashEnded = false; 627 processCommandLine(getEnvironmentInfoService().getNonFrameworkArgs()); 628 initializeDebugFlags(); 629 initialized = true; 630 initializeAuthorizationHandler(); 631 startServices(); 632 } 633 634 /** 635 * Shutdown runtime pieces in this order: 636 * Content[auto shutdown] -> Preferences[auto shutdown] -> Registry -> Jobs. 637 * The "auto" shutdown takes place before this code is executed 638 */ stop(BundleContext bundleContext)639 public void stop(BundleContext bundleContext) { 640 assertInitialized(); 641 stopServices(); // should be done after preferences shutdown 642 initialized = false; 643 closeOSGITrackers(); 644 context = null; 645 } 646 openOSGiTrackers()647 private void openOSGiTrackers() { 648 Filter filter = null; 649 try { 650 filter = context.createFilter(Location.INSTANCE_FILTER); 651 } catch (InvalidSyntaxException e) { 652 // ignore this. It should never happen as we have tested the above format. 653 } 654 instanceLocation = new ServiceTracker<>(context, filter, null); 655 instanceLocation.open(); 656 657 try { 658 filter = context.createFilter(Location.USER_FILTER); 659 } catch (InvalidSyntaxException e) { 660 // ignore this. It should never happen as we have tested the above format. 661 } 662 userLocation = new ServiceTracker<>(context, filter, null); 663 userLocation.open(); 664 665 try { 666 filter = context.createFilter(Location.CONFIGURATION_FILTER); 667 } catch (InvalidSyntaxException e) { 668 // ignore this. It should never happen as we have tested the above format. 669 } 670 configurationLocation = new ServiceTracker<>(context, filter, null); 671 configurationLocation.open(); 672 673 try { 674 filter = context.createFilter(Location.INSTALL_FILTER); 675 } catch (InvalidSyntaxException e) { 676 // ignore this. It should never happen as we have tested the above format. 677 } 678 installLocation = new ServiceTracker<>(context, filter, null); 679 installLocation.open(); 680 681 if (context != null) { 682 logTracker = new ServiceTracker<>(context, FrameworkLog.class, null); 683 logTracker.open(); 684 } 685 686 if (context != null) { 687 platformTracker = new ServiceTracker<>(context, PlatformAdmin.class, null); 688 platformTracker.open(); 689 } 690 691 if (context != null) { 692 contentTracker = new ServiceTracker<>(context, IContentTypeManager.class, null); 693 contentTracker.open(); 694 } 695 696 if (context != null) { 697 preferencesTracker = new ServiceTracker<>(context, IPreferencesService.class, null); 698 preferencesTracker.open(); 699 } 700 701 try { 702 filter = context.createFilter("(objectClass=" + IBundleGroupProvider.class.getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ 703 } catch (InvalidSyntaxException e) { 704 // ignore this, it should never happen 705 } 706 groupProviderTracker = new ServiceTracker<>(context, filter, null); 707 groupProviderTracker.open(); 708 709 logReaderTracker = new ServiceTracker<>(context, ExtendedLogReaderService.class, null); 710 logReaderTracker.open(); 711 712 extendedLogTracker = new ServiceTracker<>(context, ExtendedLogService.class, null); 713 extendedLogTracker.open(); 714 715 environmentTracker = new ServiceTracker<>(context, EnvironmentInfo.class, null); 716 environmentTracker.open(); 717 718 debugTracker = new ServiceTracker<>(context, DebugOptions.class, null); 719 debugTracker.open(); 720 } 721 startServices()722 private void startServices() { 723 // The check for getProduct() is relatively expensive (about 3% of the headless startup), 724 // so we don't want to enforce it here. 725 customPreferencesService = context.registerService(IProductPreferencesService.class, new ProductPreferencesService(), new Hashtable<>()); 726 727 legacyPreferencesService = context.registerService(ILegacyPreferences.class, new InitLegacyPreferences(), new Hashtable<>()); 728 } 729 stopServices()730 private void stopServices() { 731 if (legacyPreferencesService != null) { 732 legacyPreferencesService.unregister(); 733 legacyPreferencesService = null; 734 } 735 if (customPreferencesService != null) { 736 customPreferencesService.unregister(); 737 customPreferencesService = null; 738 } 739 } 740 getDebugOptions()741 private DebugOptions getDebugOptions() { 742 return debugTracker == null ? null : debugTracker.getService(); 743 } 744 closeOSGITrackers()745 private void closeOSGITrackers() { 746 if (preferencesTracker != null) { 747 preferencesTracker.close(); 748 } 749 if (contentTracker != null) { 750 contentTracker.close(); 751 } 752 if (debugTracker != null) { 753 debugTracker.close(); 754 } 755 if (platformTracker != null) { 756 platformTracker.close(); 757 } 758 if (logTracker != null) { 759 logTracker.close(); 760 } 761 if (groupProviderTracker != null) { 762 groupProviderTracker.close(); 763 } 764 if (environmentTracker != null) { 765 environmentTracker.close(); 766 } 767 if (logReaderTracker != null) { 768 logReaderTracker.close(); 769 } 770 if (extendedLogTracker != null) { 771 extendedLogTracker.close(); 772 } 773 if (installLocation != null) { 774 installLocation.close(); 775 } 776 if (userLocation != null) { 777 userLocation.close(); 778 } 779 if (configurationLocation != null) { 780 configurationLocation.close(); 781 } 782 if (instanceLocation != null) { 783 instanceLocation.close(); 784 } 785 } 786 787 /** 788 * Print a debug message to the console. 789 * Pre-pend the message with the current date and the name of the current thread. 790 */ message(String message)791 public static void message(String message) { 792 StringBuilder buffer = new StringBuilder(); 793 buffer.append(new Date(System.currentTimeMillis())); 794 buffer.append(" - ["); //$NON-NLS-1$ 795 buffer.append(Thread.currentThread().getName()); 796 buffer.append("] "); //$NON-NLS-1$ 797 buffer.append(message); 798 System.out.println(buffer.toString()); 799 } 800 start(Bundle bundle)801 public static void start(Bundle bundle) throws BundleException { 802 int originalState = bundle.getState(); 803 if ((originalState & Bundle.ACTIVE) != 0) 804 return; // bundle is already active 805 try { 806 // attempt to activate the bundle 807 bundle.start(Bundle.START_TRANSIENT); 808 } catch (BundleException e) { 809 if ((originalState & Bundle.STARTING) != 0 && (bundle.getState() & Bundle.STARTING) != 0) 810 // This can happen if the bundle was in the process of being activated on this thread, just return 811 return; 812 throw e; 813 } 814 } 815 } 816