package org.eclipse.core.internal.runtime;
import java.io.File;
import java.net.URL;
import java.util.*;
import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences;
import org.eclipse.core.internal.preferences.exchange.IProductPreferencesService;
import org.eclipse.core.internal.preferences.legacy.InitLegacyPreferences;
import org.eclipse.core.internal.preferences.legacy.ProductPreferencesService;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.equinox.internal.app.*;
import org.eclipse.equinox.internal.app.Activator;
import org.eclipse.equinox.log.*;
import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
import org.osgi.framework.*;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.wiring.*;
import org.osgi.resource.Namespace;
import org.osgi.util.tracker.ServiceTracker;
public final class InternalPlatform {
private static final String[] ARCH_LIST = { Platform.ARCH_X86, Platform.ARCH_X86_64 };
public static boolean DEBUG = false;
public static boolean DEBUG_PLUGIN_PREFERENCES = false;
private boolean splashEnded = false;
private boolean initialized;
private static final String KEYRING = "-keyring";
private String keyringFile;
private Map<Bundle,Log> logs = new HashMap<>(5);
private static final String[] OS_LIST = { Platform.OS_LINUX, Platform.OS_MACOSX, Platform.OS_WIN32 };
private String password = "";
private static final String PASSWORD = "-password";
public static final String PROP_APPLICATION = "eclipse.application";
public static final String PROP_ARCH = "osgi.arch";
public static final String PROP_CONFIG_AREA = "osgi.configuration.area";
public static final String PROP_CONSOLE_LOG = "eclipse.consoleLog";
public static final String PROP_DEBUG = "osgi.debug";
public static final String PROP_DEV = "osgi.dev";
public static final String PROP_INSTALL_AREA = "osgi.install.area";
public static final String PROP_NL = "osgi.nl";
public static final String PROP_OS = "osgi.os";
public static final String PROP_PRODUCT = "eclipse.product";
public static final String PROP_WS = "osgi.ws";
public static final String PROP_ACTIVATE_PLUGINS = "eclipse.activateRuntimePlugins";
private static final InternalPlatform singleton = new InternalPlatform();
private static final String[] WS_LIST = { Platform.WS_COCOA, Platform.WS_GTK, Platform.WS_WIN32, Platform.WS_WPF };
private Path cachedInstanceLocation;
private ServiceTracker<Location,Location> configurationLocation = null;
private BundleContext context;
private FrameworkWiring fwkWiring;
private Map<IBundleGroupProvider,ServiceRegistration<IBundleGroupProvider>> groupProviders = new HashMap<>(3);
private ServiceTracker<Location,Location> installLocation = null;
private ServiceTracker<Location,Location> instanceLocation = null;
private ServiceTracker<Location,Location> userLocation = null;
private Plugin runtimeInstance;
private ServiceRegistration<ILegacyPreferences> legacyPreferencesService = null;
private ServiceRegistration<IProductPreferencesService> customPreferencesService = null;
private ServiceTracker<EnvironmentInfo,EnvironmentInfo> environmentTracker = null;
private ServiceTracker<FrameworkLog,FrameworkLog> logTracker = null;
private ServiceTracker<PlatformAdmin, PlatformAdmin> platformTracker = null;
private ServiceTracker<DebugOptions,DebugOptions> debugTracker = null;
private ServiceTracker<IContentTypeManager,IContentTypeManager> contentTracker = null;
private ServiceTracker<IPreferencesService,IPreferencesService> preferencesTracker = null;
private ServiceTracker<IBundleGroupProvider,IBundleGroupProvider> groupProviderTracker = null;
private ServiceTracker<ExtendedLogReaderService,ExtendedLogReaderService> logReaderTracker = null;
private ServiceTracker<ExtendedLogService,ExtendedLogService> extendedLogTracker = null;
private IProduct product;
public static InternalPlatform getDefault() {
return singleton;
}
private InternalPlatform() {
super();
}
public void addLogListener(ILogListener listener) {
assertInitialized();
RuntimeLog.addLogListener(listener);
}
private void assertInitialized() {
if (!initialized)
Assert.isTrue(false, Messages.meta_appNotInit);
}
public void endSplash() {
synchronized (this) {
if (splashEnded)
return;
splashEnded = true;
}
IApplicationContext applicationContext = getApplicationContext();
if (applicationContext != null)
applicationContext.applicationRunning();
}
public IAdapterManager getAdapterManager() {
assertInitialized();
return AdapterManager.getDefault();
}
public String[] getApplicationArgs() {
return CommandLineArgs.getApplicationArgs();
}
public boolean getBooleanOption(String option, boolean defaultValue) {
String value = getOption(option);
if (value == null)
return defaultValue;
return value.equalsIgnoreCase("true");
}
public BundleContext getBundleContext() {
return context;
}
public String getBundleId(Object object) {
if (object == null)
return null;
Bundle source = FrameworkUtil.getBundle(object.getClass());
if (source != null && source.getSymbolicName() != null)
return source.getSymbolicName();
return null;
}
public IBundleGroupProvider[] getBundleGroupProviders() {
return groupProviderTracker.getServices(new IBundleGroupProvider[0]);
}
public void registerBundleGroupProvider(IBundleGroupProvider provider) {
ServiceRegistration<IBundleGroupProvider> registration = getBundleContext().registerService(IBundleGroupProvider.class, provider, null);
synchronized (groupProviders) {
groupProviders.put(provider, registration);
}
}
public void unregisterBundleGroupProvider(IBundleGroupProvider provider) {
ServiceRegistration<IBundleGroupProvider> registration;
synchronized (groupProviders) {
registration = groupProviders.remove(provider);
}
if (registration == null)
return;
registration.unregister();
}
public Bundle getBundle(String symbolicName) {
Bundle[] bundles = getBundles(symbolicName, null);
return bundles != null && bundles.length > 0 ? bundles[0] : null;
}
public Bundle[] getBundles(String symbolicName, String versionRange) {
if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) {
symbolicName = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getSymbolicName();
}
Map<String, String> directives = Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE,
getRequirementFilter(symbolicName, versionRange));
Collection<BundleCapability> matchingBundleCapabilities = fwkWiring.findProviders(ModuleContainer
.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, directives, Collections.emptyMap()));
if (matchingBundleCapabilities.isEmpty()) {
return null;
}
Bundle[] results = matchingBundleCapabilities.stream().map(c -> c.getRevision().getBundle())
.filter(bundle -> (bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0)
.sorted((b1, b2) -> b2.getVersion().compareTo(b1.getVersion()))
.toArray(Bundle[]::new);
return results.length > 0 ? results : null;
}
private String getRequirementFilter(String symbolicName, String versionRange) {
VersionRange range = versionRange == null ? null : new VersionRange(versionRange);
StringBuilder filter = new StringBuilder();
if (range != null) {
filter.append("(&");
}
filter.append('(').append(IdentityNamespace.IDENTITY_NAMESPACE).append('=').append(symbolicName).append(')');
if (range != null) {
filter.append(range.toFilterString(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE)).append(')');
}
return filter.toString();
}
public String[] getCommandLineArgs() {
return CommandLineArgs.getAllArgs();
}
public Location getConfigurationLocation() {
assertInitialized();
return configurationLocation.getService();
}
public IContentTypeManager getContentTypeManager() {
return contentTracker == null ? null : (IContentTypeManager) contentTracker.getService();
}
public EnvironmentInfo getEnvironmentInfoService() {
return environmentTracker == null ? null : (EnvironmentInfo) environmentTracker.getService();
}
public FrameworkLog getFrameworkLog() {
return logTracker == null ? null : (FrameworkLog) logTracker.getService();
}
public Bundle[] getFragments(Bundle bundle) {
BundleWiring wiring = bundle.adapt(BundleWiring.class);
if (wiring == null) {
return null;
}
List<BundleWire> hostWires = wiring.getProvidedWires(HostNamespace.HOST_NAMESPACE);
if (hostWires == null) {
return null;
}
Bundle[] result = hostWires.stream().map(wire -> wire.getRequirer().getBundle()).filter(Objects::nonNull)
.toArray(Bundle[]::new);
return result.length > 0 ? result : null;
}
public Bundle[] getHosts(Bundle bundle) {
BundleWiring wiring = bundle.adapt(BundleWiring.class);
if (wiring == null) {
return null;
}
List<BundleWire> hostWires = wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE);
if (hostWires == null) {
return null;
}
Bundle[] result = hostWires.stream().map(wire -> wire.getProvider().getBundle()).filter(Objects::nonNull)
.toArray(Bundle[]::new);
return result.length > 0 ? result : null;
}
public Location getInstallLocation() {
assertInitialized();
return installLocation.getService();
}
public URL getInstallURL() {
Location location = getInstallLocation();
if (location == null)
throw new IllegalStateException("The installation location must not be null");
return location.getURL();
}
public Location getInstanceLocation() {
assertInitialized();
return instanceLocation.getService();
}
public IPath getLocation() throws IllegalStateException {
if (cachedInstanceLocation == null) {
Location location = getInstanceLocation();
if (location == null)
return null;
File file = new File(location.getURL().getFile());
cachedInstanceLocation = new Path(file.toString());
}
return cachedInstanceLocation;
}
public ILog getLog(Bundle bundle) {
Log result = logs.get(bundle);
if (result != null)
return result;
ExtendedLogService logService = extendedLogTracker.getService();
Logger logger = logService == null ? null : logService.getLogger(bundle, PlatformLogWriter.EQUINOX_LOGGER_NAME);
result = new Log(bundle, logger);
ExtendedLogReaderService logReader = logReaderTracker.getService();
logReader.addLogListener(result, result);
logs.put(bundle, result);
return result;
}
public String getNL() {
return getBundleContext().getProperty(PROP_NL);
}
public String getNLExtensions() {
String nlExtensions = PlatformActivator.getContext().getProperty("osgi.nl.extensions");
if (nlExtensions == null)
return "";
if (!nlExtensions.startsWith("@"))
nlExtensions = '@' + nlExtensions;
return nlExtensions;
}
public String getOption(String option) {
DebugOptions options = getDebugOptions();
if (options != null)
return options.getOption(option);
return null;
}
public String getOS() {
return getBundleContext().getProperty(PROP_OS);
}
public String getOSArch() {
return getBundleContext().getProperty(PROP_ARCH);
}
public PlatformAdmin getPlatformAdmin() {
return platformTracker == null ? null : platformTracker.getService();
}
public IPreferencesService getPreferencesService() {
return preferencesTracker == null ? null : (IPreferencesService) preferencesTracker.getService();
}
public IProduct getProduct() {
if (product != null)
return product;
EclipseAppContainer container = Activator.getContainer();
IBranding branding = container == null ? null : container.getBranding();
if (branding == null)
return null;
Object brandingProduct = branding.getProduct();
if (!(brandingProduct instanceof IProduct))
brandingProduct = new Product(branding);
product = (IProduct) brandingProduct;
return product;
}
public IExtensionRegistry getRegistry() {
return RegistryFactory.getRegistry();
}
public ResourceBundle getResourceBundle(Bundle bundle) {
return ResourceTranslator.getResourceBundle(bundle);
}
public String getResourceString(Bundle bundle, String value) {
return ResourceTranslator.getResourceString(bundle, value);
}
public String getResourceString(Bundle bundle, String value, ResourceBundle resourceBundle) {
return ResourceTranslator.getResourceString(bundle, value, resourceBundle);
}
public Plugin getRuntimeInstance() {
return runtimeInstance;
}
private IApplicationContext getApplicationContext() {
Collection<ServiceReference<IApplicationContext>> references;
try {
references = context.getServiceReferences(IApplicationContext.class, "(eclipse.application.type=main.thread)");
} catch (InvalidSyntaxException e) {
return null;
}
if (references == null || references.isEmpty())
return null;
ServiceReference<IApplicationContext> firstRef = references.iterator().next();
IApplicationContext result = context.getService(firstRef);
if (result != null) {
context.ungetService(firstRef);
return result;
}
return null;
}
public IPath getStateLocation(Bundle bundle) {
return getStateLocation(bundle, true);
}
public IPath getStateLocation(Bundle bundle, boolean create) throws IllegalStateException {
assertInitialized();
IPath result = MetaDataKeeper.getMetaArea().getStateLocation(bundle);
if (create)
result.toFile().mkdirs();
return result;
}
public long getStateTimeStamp() {
PlatformAdmin admin = getPlatformAdmin();
return admin == null ? -1 : admin.getState(false).getTimeStamp();
}
public Location getUserLocation() {
assertInitialized();
return userLocation.getService();
}
public String getWS() {
return getBundleContext().getProperty(PROP_WS);
}
private void initializeAuthorizationHandler() {
try {
AuthorizationHandler.setKeyringFile(keyringFile);
AuthorizationHandler.setPassword(password);
} catch (NoClassDefFoundError e) {
}
}
void initializeDebugFlags() {
DEBUG = getBooleanOption(Platform.PI_RUNTIME + "/debug", false);
if (DEBUG) {
DEBUG_PLUGIN_PREFERENCES = getBooleanOption(Platform.PI_RUNTIME + "/preferences/plugin", false);
}
}
public boolean isFragment(Bundle bundle) {
BundleRevisions bundleRevisions = bundle.adapt(BundleRevisions.class);
List<BundleRevision> revisions = bundleRevisions.getRevisions();
if (revisions.isEmpty()) {
return false;
}
return (revisions.get(0).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
}
public boolean isRunning() {
try {
return initialized && context != null && context.getBundle().getState() == Bundle.ACTIVE;
} catch (IllegalStateException e) {
return false;
}
}
public String[] knownOSArchValues() {
return ARCH_LIST;
}
public String[] knownOSValues() {
return OS_LIST;
}
public String[] knownWSValues() {
return WS_LIST;
}
private void processCommandLine(String[] args) {
if (args == null || args.length == 0)
return;
for (int i = 0; i < args.length; i++) {
if (i == args.length - 1 || args[i + 1].startsWith("-"))
continue;
String arg = args[++i];
if (args[i - 1].equalsIgnoreCase(KEYRING))
keyringFile = arg;
if (args[i - 1].equalsIgnoreCase(PASSWORD))
password = arg;
}
}
public void removeLogListener(ILogListener listener) {
assertInitialized();
RuntimeLog.removeLogListener(listener);
}
public void setRuntimeInstance(Plugin runtime) {
runtimeInstance = runtime;
}
public void start(BundleContext runtimeContext) {
this.context = runtimeContext;
this.fwkWiring = runtimeContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class);
openOSGiTrackers();
splashEnded = false;
processCommandLine(getEnvironmentInfoService().getNonFrameworkArgs());
initializeDebugFlags();
initialized = true;
initializeAuthorizationHandler();
startServices();
}
public void stop(BundleContext bundleContext) {
assertInitialized();
stopServices();
initialized = false;
closeOSGITrackers();
context = null;
}
private void openOSGiTrackers() {
Filter filter = null;
try {
filter = context.createFilter(Location.INSTANCE_FILTER);
} catch (InvalidSyntaxException e) {
}
instanceLocation = new ServiceTracker<>(context, filter, null);
instanceLocation.open();
try {
filter = context.createFilter(Location.USER_FILTER);
} catch (InvalidSyntaxException e) {
}
userLocation = new ServiceTracker<>(context, filter, null);
userLocation.open();
try {
filter = context.createFilter(Location.CONFIGURATION_FILTER);
} catch (InvalidSyntaxException e) {
}
configurationLocation = new ServiceTracker<>(context, filter, null);
configurationLocation.open();
try {
filter = context.createFilter(Location.INSTALL_FILTER);
} catch (InvalidSyntaxException e) {
}
installLocation = new ServiceTracker<>(context, filter, null);
installLocation.open();
if (context != null) {
logTracker = new ServiceTracker<>(context, FrameworkLog.class, null);
logTracker.open();
}
if (context != null) {
platformTracker = new ServiceTracker<>(context, PlatformAdmin.class, null);
platformTracker.open();
}
if (context != null) {
contentTracker = new ServiceTracker<>(context, IContentTypeManager.class, null);
contentTracker.open();
}
if (context != null) {
preferencesTracker = new ServiceTracker<>(context, IPreferencesService.class, null);
preferencesTracker.open();
}
try {
filter = context.createFilter("(objectClass=" + IBundleGroupProvider.class.getName() + ")");
} catch (InvalidSyntaxException e) {
}
groupProviderTracker = new ServiceTracker<>(context, filter, null);
groupProviderTracker.open();
logReaderTracker = new ServiceTracker<>(context, ExtendedLogReaderService.class, null);
logReaderTracker.open();
extendedLogTracker = new ServiceTracker<>(context, ExtendedLogService.class, null);
extendedLogTracker.open();
environmentTracker = new ServiceTracker<>(context, EnvironmentInfo.class, null);
environmentTracker.open();
debugTracker = new ServiceTracker<>(context, DebugOptions.class, null);
debugTracker.open();
}
private void startServices() {
customPreferencesService = context.registerService(IProductPreferencesService.class, new ProductPreferencesService(), new Hashtable<>());
legacyPreferencesService = context.registerService(ILegacyPreferences.class, new InitLegacyPreferences(), new Hashtable<>());
}
private void stopServices() {
if (legacyPreferencesService != null) {
legacyPreferencesService.unregister();
legacyPreferencesService = null;
}
if (customPreferencesService != null) {
customPreferencesService.unregister();
customPreferencesService = null;
}
}
private DebugOptions getDebugOptions() {
return debugTracker == null ? null : debugTracker.getService();
}
private void closeOSGITrackers() {
if (preferencesTracker != null) {
preferencesTracker.close();
preferencesTracker = null;
}
if (contentTracker != null) {
contentTracker.close();
contentTracker = null;
}
if (debugTracker != null) {
debugTracker.close();
debugTracker = null;
}
if (platformTracker != null) {
platformTracker.close();
platformTracker = null;
}
if (logTracker != null) {
logTracker.close();
logTracker = null;
}
if (groupProviderTracker != null) {
groupProviderTracker.close();
groupProviderTracker = null;
}
if (environmentTracker != null) {
environmentTracker.close();
environmentTracker = null;
}
if (logReaderTracker != null) {
logReaderTracker.close();
logReaderTracker = null;
}
if (extendedLogTracker != null) {
extendedLogTracker.close();
extendedLogTracker = null;
}
if (installLocation != null) {
installLocation.close();
installLocation = null;
}
if (userLocation != null) {
userLocation.close();
userLocation = null;
}
if (configurationLocation != null) {
configurationLocation.close();
configurationLocation = null;
}
if (instanceLocation != null) {
instanceLocation.close();
instanceLocation = null;
}
}
public static void message(String message) {
StringBuilder buffer = new StringBuilder();
buffer.append(new Date(System.currentTimeMillis()));
buffer.append(" - [");
buffer.append(Thread.currentThread().getName());
buffer.append("] ");
buffer.append(message);
System.out.println(buffer.toString());
}
public static void start(Bundle bundle) throws BundleException {
int originalState = bundle.getState();
if ((originalState & Bundle.ACTIVE) != 0)
return;
try {
bundle.start(Bundle.START_TRANSIENT);
} catch (BundleException e) {
if ((originalState & Bundle.STARTING) != 0 && (bundle.getState() & Bundle.STARTING) != 0)
return;
throw e;
}
}
}