blob: 66c979b07141948ab3705911b22747f34aad995b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.core;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.eclipse.pde.core.IBundleClasspathResolver;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.project.IBundleProjectService;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetPlatformService;
import org.eclipse.pde.internal.core.builders.FeatureRebuilder;
import org.eclipse.pde.internal.core.builders.PluginRebuilder;
import org.eclipse.pde.internal.core.project.BundleProjectService;
import org.eclipse.pde.internal.core.schema.SchemaRegistry;
import org.eclipse.pde.internal.core.target.P2TargetUtils;
import org.eclipse.pde.internal.core.target.TargetPlatformService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
public class PDECore extends Plugin implements DebugOptionsListener {
public static final String PLUGIN_ID = "org.eclipse.pde.core"; //$NON-NLS-1$
public static final IPath REQUIRED_PLUGINS_CONTAINER_PATH = new Path(PLUGIN_ID + ".requiredPlugins"); //$NON-NLS-1$
public static final IPath JAVA_SEARCH_CONTAINER_PATH = new Path(PLUGIN_ID + ".externalJavaSearch"); //$NON-NLS-1$
public static final IPath JRE_CONTAINER_PATH = new Path(JavaRuntime.JRE_CONTAINER);
public static final String BINARY_PROJECT_VALUE = "binary"; //$NON-NLS-1$
public static final String BINARY_REPOSITORY_PROVIDER = PLUGIN_ID + "." + "BinaryRepositoryProvider"; //$NON-NLS-1$ //$NON-NLS-2$
public static final QualifiedName EXTERNAL_PROJECT_PROPERTY = new QualifiedName(PLUGIN_ID, "imported"); //$NON-NLS-1$
public static final QualifiedName TOUCH_PROJECT = new QualifiedName(PLUGIN_ID, "TOUCH_PROJECT"); //$NON-NLS-1$
public static final QualifiedName SCHEMA_PREVIEW_FILE = new QualifiedName(PLUGIN_ID, "SCHEMA_PREVIEW_FILE"); //$NON-NLS-1$
public static boolean DEBUG_CLASSPATH = false;
public static boolean DEBUG_MODEL = false;
public static boolean DEBUG_TARGET_PROFILE = false;
public static boolean DEBUG_VALIDATION = false;
private static final String DEBUG_FLAG = PLUGIN_ID + "/debug"; //$NON-NLS-1$
private static final String CLASSPATH_DEBUG = PLUGIN_ID + "/classpath"; //$NON-NLS-1$
private static final String MODEL_DEBUG = PLUGIN_ID + "/model"; //$NON-NLS-1$
private static final String TARGET_PROFILE_DEBUG = PLUGIN_ID + "/target/profile"; //$NON-NLS-1$
private static final String VALIDATION_DEBUG = PLUGIN_ID + "/validation"; //$NON-NLS-1$
// Shared instance
private static PDECore inst;
private static PDEExtensionRegistry fExtensionRegistry = null;
/**
* The singleton preference manager instance
*
* @since 3.5
*/
private static PDEPreferencesManager fPreferenceManager;
private Map<String, IPluginModelBase> fHostPlugins;
public static PDECore getDefault() {
return inst;
}
/**
* Returns the singleton instance of if the {@link PDEPreferencesManager} for this bundle
* @return the preference manager for this bundle
*
* @since 3.5
*/
public synchronized PDEPreferencesManager getPreferencesManager() {
if (fPreferenceManager == null) {
fPreferenceManager = new PDEPreferencesManager(PLUGIN_ID);
}
return fPreferenceManager;
}
public static IWorkspace getWorkspace() {
return ResourcesPlugin.getWorkspace();
}
public static void log(IStatus status) {
if (status != null) {
ResourcesPlugin.getPlugin().getLog().log(status);
}
}
public static void log(Throwable e) {
if (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e).getTargetException();
}
IStatus status = null;
if (e instanceof CoreException || e.getMessage() != null) {
status = Status.error(e.getMessage(), e);
}
log(status);
}
public static void logErrorMessage(String message) {
log(Status.error(message));
}
public static void logException(Throwable e) {
logException(e, null);
}
public static void logException(Throwable e, String message) {
if (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e).getTargetException();
}
IStatus status = null;
if (e instanceof CoreException) {
status = Status.error(message, e);
} else {
if (message == null) {
message = e.getMessage();
}
if (message == null) {
message = e.toString();
}
status = Status.error(message, e);
}
log(status);
}
private FeatureModelManager fFeatureModelManager;
private TargetDefinitionManager fTargetProfileManager;
// Schema registry
private SchemaRegistry fSchemaRegistry;
private SourceLocationManager fSourceLocationManager;
private JavadocLocationManager fJavadocLocationManager;
private SearchablePluginsManager fSearchablePluginsManager;
private ClasspathContainerResolverManager fClasspathContainerResolverManager;
// Tracing options manager
private TracingOptionsManager fTracingOptionsManager;
private BundleContext fBundleContext;
private JavaElementChangeListener fJavaElementChangeListener;
private FeatureRebuilder fFeatureRebuilder;
private PluginRebuilder fPluginRebuilder;
/**
* Target platform service.
*/
private ServiceRegistration<ITargetPlatformService> fTargetPlatformService;
/**
* Bundle project service.
*/
private ServiceRegistration<IBundleProjectService> fBundleProjectService;
public PDECore() {
inst = this;
}
public synchronized IPluginModelBase findPluginInHost(String id) {
if (fHostPlugins == null) {
fHostPlugins = new HashMap<>();
ITargetDefinition defaultTarget = TargetPlatformService.getDefault().newDefaultTarget();
IStatus status = defaultTarget.resolve(new NullProgressMonitor());
if (!status.isOK()) {
log(status);
return null;
}
URI[] pluginPaths = Arrays.stream(defaultTarget.getBundles()) //
.filter(b -> !b.isSourceBundle()) //
.map(b -> b.getBundleInfo().getLocation()) //
.toArray(URI[]::new);
PDEState state = new PDEState(pluginPaths, true, false, new NullProgressMonitor());
state.resolveState(false);
for (IPluginModelBase plugin : state.getTargetModels()) {
fHostPlugins.put(plugin.getPluginBase().getId(), plugin);
}
}
return fHostPlugins.get(id);
}
public PluginModelManager getModelManager() {
return PluginModelManager.getInstance();
}
public synchronized TargetDefinitionManager getTargetProfileManager() {
if (fTargetProfileManager == null) {
fTargetProfileManager = new TargetDefinitionManager();
}
return fTargetProfileManager;
}
public synchronized FeatureModelManager getFeatureModelManager() {
if (fFeatureModelManager == null) {
fFeatureModelManager = new FeatureModelManager();
}
return fFeatureModelManager;
}
public JavaElementChangeListener getJavaElementChangeListener() {
return fJavaElementChangeListener;
}
public synchronized SchemaRegistry getSchemaRegistry() {
if (fSchemaRegistry == null) {
fSchemaRegistry = new SchemaRegistry();
}
return fSchemaRegistry;
}
public synchronized PDEExtensionRegistry getExtensionsRegistry() {
if (fExtensionRegistry == null) {
fExtensionRegistry = new PDEExtensionRegistry();
}
return fExtensionRegistry;
}
public synchronized SourceLocationManager getSourceLocationManager() {
if (fSourceLocationManager == null) {
fSourceLocationManager = new SourceLocationManager();
}
return fSourceLocationManager;
}
/**
* Returns the singleton instance of the classpath container resolver manager used to dynamically
* resolve a project's classpath. Clients may contribute a {@link IBundleClasspathResolver} to the
* manager through the <code>org.eclipse.pde.core.bundleClasspathResolvers</code> extension.
*
* @return singleton instance of the classpath container resolver manager
*/
public synchronized ClasspathContainerResolverManager getClasspathContainerResolverManager() {
if (fClasspathContainerResolverManager == null) {
fClasspathContainerResolverManager = new ClasspathContainerResolverManager();
}
return fClasspathContainerResolverManager;
}
public synchronized JavadocLocationManager getJavadocLocationManager() {
if (fJavadocLocationManager == null) {
fJavadocLocationManager = new JavadocLocationManager();
}
return fJavadocLocationManager;
}
public synchronized TracingOptionsManager getTracingOptionsManager() {
if (fTracingOptionsManager == null) {
fTracingOptionsManager = new TracingOptionsManager();
}
return fTracingOptionsManager;
}
public synchronized SearchablePluginsManager getSearchablePluginsManager() {
if (fSearchablePluginsManager == null) {
fSearchablePluginsManager = new SearchablePluginsManager();
}
return fSearchablePluginsManager;
}
public boolean areModelsInitialized() {
return getModelManager().isInitialized();
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
fBundleContext = context;
fJavaElementChangeListener = new JavaElementChangeListener();
fJavaElementChangeListener.start();
fPluginRebuilder = new PluginRebuilder();
fPluginRebuilder.start();
fFeatureRebuilder = new FeatureRebuilder();
fFeatureRebuilder.start();
fTargetPlatformService = context.registerService(ITargetPlatformService.class,
TargetPlatformService.getDefault(), new Hashtable<String, Object>());
fBundleProjectService = context.registerService(IBundleProjectService.class, BundleProjectService.getDefault(),
new Hashtable<String, Object>());
// Register the debug options listener service (tracing)
Hashtable<String, String> props = new Hashtable<>(2);
props.put(org.eclipse.osgi.service.debug.DebugOptions.LISTENER_SYMBOLICNAME, PDECore.PLUGIN_ID);
context.registerService(DebugOptionsListener.class.getName(), this, props);
// use save participant to clean orphaned profiles.
ResourcesPlugin.getWorkspace().addSaveParticipant(PLUGIN_ID, new ISaveParticipant() {
@Override
public void saving(ISaveContext saveContext) throws CoreException {
P2TargetUtils.cleanOrphanedTargetDefinitionProfiles();
}
@Override
public void rollback(ISaveContext saveContext) {
}
@Override
public void prepareToSave(ISaveContext saveContext) throws CoreException {
}
@Override
public void doneSaving(ISaveContext saveContext) {
}
});
}
public BundleContext getBundleContext() {
return fBundleContext;
}
@Override
public void stop(BundleContext context) throws CoreException {
if (fPreferenceManager != null) {
fPreferenceManager.savePluginPreferences();
}
fJavaElementChangeListener.shutdown();
fPluginRebuilder.stop();
fFeatureRebuilder.stop();
if (fSchemaRegistry != null) {
fSchemaRegistry.shutdown();
fSchemaRegistry = null;
}
if (fTargetProfileManager != null) {
fTargetProfileManager.shutdown();
fTargetProfileManager = null;
}
if (fSearchablePluginsManager != null) {
fSearchablePluginsManager.shutdown();
fSearchablePluginsManager = null;
}
if (fFeatureModelManager != null) {
fFeatureModelManager.shutdown();
fFeatureModelManager = null;
}
// always shut down extension registry before model manager (since it needs data from model manager)
if (fExtensionRegistry != null) {
fExtensionRegistry.stop();
fExtensionRegistry = null;
}
PluginModelManager.shutdownInstance();
if (fTargetPlatformService != null) {
fTargetPlatformService.unregister();
fTargetPlatformService = null;
}
if (fBundleProjectService != null) {
fBundleProjectService.unregister();
fBundleProjectService = null;
}
ResourcesPlugin.getWorkspace().removeSaveParticipant(PLUGIN_ID);
}
/**
* Returns a service for the specified class or <code>null</code> if none.
*
* @param serviceClass
* class of service
* @return service service or <code>null</code> if none
*/
public <T> T acquireService(Class<T> serviceClass) {
ServiceReference<T> reference = fBundleContext.getServiceReference(serviceClass);
if (reference == null) {
return null;
}
T service = fBundleContext.getService(reference);
if (service != null) {
fBundleContext.ungetService(reference);
}
return service;
}
@Override
public void optionsChanged(DebugOptions options) {
boolean DEBUG = options.getBooleanOption(DEBUG_FLAG, false);
DEBUG_CLASSPATH = DEBUG && options.getBooleanOption(CLASSPATH_DEBUG, false);
DEBUG_MODEL = DEBUG && options.getBooleanOption(MODEL_DEBUG, false);
DEBUG_TARGET_PROFILE = DEBUG && options.getBooleanOption(TARGET_PROFILE_DEBUG, false);
DEBUG_VALIDATION = DEBUG && options.getBooleanOption(VALIDATION_DEBUG, false);
}
}