blob: 739cb95aa59b3546a73fd400567d16b3a3485d67 [file] [log] [blame]
package org.eclipse.core.internal.plugins;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.model.*;
import org.eclipse.core.internal.runtime.*;
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.*;
public class PluginRegistry extends PluginRegistryModel implements IPluginRegistry {
private static final String URL_PROTOCOL_FILE = "file";
private static final String F_DEBUG_REGISTRY = ".debugregistry";
// lifecycle events
private static final int STARTUP = 0;
private static final int SHUTDOWN = 1;
public PluginRegistry()
{
super();
}
/**
* Iterate over the plug-ins in this registry. Plug-ins are visited in dependent order. That is,
* a plug-in, A, which requires another plug-in, B, is visited before its dependents (i.e., A is
* visited before B).
*/
public void accept(IPluginVisitor visitor, boolean activeOnly) {
Map dependents = getDependentCounts(activeOnly);
// keep iterating until all have been visited.
while (!dependents.isEmpty()) {
// loop over the dependents list. For each entry, if there are no dependents, visit
// the plugin and remove it from the list. Make a copy of the keys so we don't end up
// with concurrent accesses (since we are deleting the values as we go)
PluginDescriptor[] keys = (PluginDescriptor[]) dependents.keySet().toArray(new PluginDescriptor[dependents.size()]);
for (int i = 0; i < keys.length; i++) {
PluginDescriptor descriptor = keys[i];
Integer entry = (Integer) dependents.get(descriptor);
if (entry != null && entry.intValue() <= 0) {
visitor.visit(descriptor);
dependents.remove(descriptor);
// decrement the dependent count for all of the prerequisites.
PluginPrerequisiteModel[] requires = descriptor.getRequires();
int reqSize = (requires == null) ? 0 : requires.length;
for (int j = 0; j < reqSize; j++) {
String id = ((PluginPrerequisite) requires[j]).getUniqueIdentifier();
PluginDescriptor prereq = (PluginDescriptor) getPlugin(id);
Integer count = (Integer) dependents.get(prereq);
if (count != null)
dependents.put(prereq, new Integer(count.intValue() - 1));
}
}
}
}
}
public IConfigurationElement[] getConfigurationElementsFor(String uniqueId) {
IExtensionPoint point = getExtensionPoint(uniqueId);
if (point == null)
return new IConfigurationElement[0];
IConfigurationElement[] result = point.getConfigurationElements();
return result == null ? new IConfigurationElement[0] : result;
}
public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String pointId) {
IExtensionPoint point = getExtensionPoint(pluginId, pointId);
if (point == null)
return new IConfigurationElement[0];
IConfigurationElement[] result = point.getConfigurationElements();
return result == null ? new IConfigurationElement[0] : result;
}
public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String pointId, String extensionId) {
IExtension extension = getExtension(pluginId, pointId, extensionId);
if (extension == null)
return new IConfigurationElement[0];
IConfigurationElement[] result = extension.getConfigurationElements();
return result == null ? new IConfigurationElement[0] : result;
}
/**
* Returns a map of the dependent counts for all plug-ins. The map's
* keys are the plug-in descriptors and the values are an (<code>Integer</code>) count of
* descriptors which depend on that plug-in.
*/
private Map getDependentCounts(boolean activeOnly) {
IPluginDescriptor[] descriptors = getPluginDescriptors();
int descSize = (descriptors == null) ? 0 : descriptors.length;
Map dependents = new HashMap(5);
// build a table of all dependent counts. The table is keyed by descriptor and
// the value the integer number of dependent plugins.
for (int i = 0; i < descSize; i++) {
if (activeOnly && !descriptors[i].isPluginActivated())
continue;
// ensure there is an entry for this descriptor (otherwise it will not be visited)
Integer entry = (Integer) dependents.get(descriptors[i]);
if (entry == null)
dependents.put(descriptors[i], new Integer(0));
PluginPrerequisiteModel[] requires = ((PluginDescriptor) descriptors[i]).getRequires();
int reqSize = (requires == null ? 0 : requires.length);
for (int j = 0; j < reqSize; j++) {
String id = ((PluginPrerequisite) requires[j]).getUniqueIdentifier();
PluginDescriptor prereq = (PluginDescriptor) getPlugin(id);
if (prereq == null || activeOnly && !prereq.isPluginActivated())
continue;
entry = (Integer) dependents.get(prereq);
entry = entry == null ? new Integer(1) : new Integer(entry.intValue() + 1);
dependents.put(prereq, entry);
}
}
return dependents;
}
public IExtension getExtension(String xptUniqueId, String extUniqueId) {
int lastdot = xptUniqueId.lastIndexOf('.');
if (lastdot == -1) return null;
return getExtension(xptUniqueId.substring(0,lastdot), xptUniqueId.substring(lastdot+1), extUniqueId);
}
public IExtension getExtension(String pluginId, String xptSimpleId, String extId) {
IExtensionPoint xpt = getExtensionPoint(pluginId, xptSimpleId);
if (xpt == null) return null;
return xpt.getExtension(extId);
}
public IExtensionPoint getExtensionPoint(String xptUniqueId) {
int lastdot = xptUniqueId.lastIndexOf('.');
if (lastdot == -1) return null;
return getExtensionPoint(xptUniqueId.substring(0,lastdot), xptUniqueId.substring(lastdot+1));
}
public IExtensionPoint getExtensionPoint(String plugin, String xpt) {
IPluginDescriptor pd = getPluginDescriptor(plugin);
if (pd == null) return null;
return pd.getExtensionPoint(xpt);
}
public IExtensionPoint[] getExtensionPoints() {
PluginDescriptorModel[] list = getPlugins();
if (list == null)
return new IExtensionPoint[0];
ArrayList result = new ArrayList();
for (int i = 0; i < list.length; i++) {
ExtensionPointModel[] pointList = list[i].getDeclaredExtensionPoints();
if (pointList != null) {
for (int j = 0; j < pointList.length; j++)
result.add(pointList[j]);
}
}
return (IExtensionPoint[]) result.toArray(new IExtensionPoint[result.size()]);
}
public IPluginDescriptor getPluginDescriptor(String plugin) {
return (IPluginDescriptor) getPlugin(plugin);
}
public IPluginDescriptor getPluginDescriptor(String pluginId, PluginVersionIdentifier version) {
PluginDescriptorModel[] plugins = getPlugins(pluginId);
if (plugins == null || plugins.length == 0)
return null;
if (version == null)
// Just return the first one in the list (random)
return (IPluginDescriptor) plugins[0];
for (int i = 0; i < plugins.length; i++) {
IPluginDescriptor element = (IPluginDescriptor) plugins[i];
if (element.getVersionIdentifier().equals(version))
return element;
}
return null;
}
public IPluginDescriptor[] getPluginDescriptors() {
PluginDescriptorModel[] plugins = getPlugins();
if (plugins==null)
return new IPluginDescriptor[0];
IPluginDescriptor[] result = new IPluginDescriptor[plugins.length];
for (int i = 0; i < plugins.length; i++)
result[i] = (IPluginDescriptor) plugins[i];
return result;
}
public IPluginDescriptor[] getPluginDescriptors(String plugin) {
PluginDescriptorModel[] plugins = getPlugins(plugin);
if (plugins==null)
return new IPluginDescriptor[0];
IPluginDescriptor[] result = new IPluginDescriptor[plugins.length];
System.arraycopy(plugins, 0, result, 0, plugins.length);
return result;
}
void logError(IStatus status) {
InternalPlatform.getRuntimePlugin().getLog().log(status);
if (InternalPlatform.DEBUG)
System.out.println(status.getMessage());
}
public void saveRegistry() throws IOException {
IPath path = InternalPlatform.getMetaArea().getRegistryPath();
IPath tempPath = InternalPlatform.getMetaArea().getBackupFilePathFor(path);
DataOutputStream output = null;
try {
output = new DataOutputStream(new BufferedOutputStream(new SafeFileOutputStream(path.toOSString(),tempPath.toOSString())));
} catch (IOException ioe) {
String message = Policy.bind("meta.unableToCreateCache");
IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, message, ioe);
logError(status);
}
try {
long start = System.currentTimeMillis();
RegistryCacheWriter cacheWriter = new RegistryCacheWriter();
cacheWriter.writePluginRegistry(this, output);
if (InternalPlatform.DEBUG)
System.out.println("Wrote registry: " + (System.currentTimeMillis() - start) + "ms");
} finally {
output.close();
}
}
public void flushRegistry() {
IPath path = InternalPlatform.getMetaArea().getRegistryPath();
IPath tempPath = InternalPlatform.getMetaArea().getBackupFilePathFor(path);
path.toFile().delete();
tempPath.toFile().delete();
}
public void debugRegistry() {
IPath path = InternalPlatform.getMetaArea().getLocation().append(F_DEBUG_REGISTRY);
try {
FileOutputStream fs = new FileOutputStream(path.toOSString());
PrintWriter w = new PrintWriter(fs);
try {
RegistryWriter regWriter = new RegistryWriter();
regWriter.writePluginRegistry(this, w, 0);
w.flush();
} finally {
w.close();
}
} catch (IOException ioe) {
String message = Policy.bind("meta.unableToCreateRegDebug");
IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, message, ioe);
logError(status);
}
}
public void flushDebugRegistry() {
IPath path = InternalPlatform.getMetaArea().getLocation().append(F_DEBUG_REGISTRY);
path.toFile().delete();
}
public void shutdown(IProgressMonitor progress) {
shutdownPlugins();
if (progress != null)
progress.worked(1);
}
private void shutdownPlugins() {
IPluginVisitor visitor = new IPluginVisitor() {
public void visit(final IPluginDescriptor descriptor) {
ISafeRunnable code = new ISafeRunnable() {
public void run() throws Exception {
if (!descriptor.isPluginActivated())
return;
try {
Plugin plugin = descriptor.getPlugin();
plugin.shutdown();
} finally {
((PluginDescriptor) descriptor).doPluginDeactivation();
}
}
public void handleException(Throwable e) {
// do nothing as the exception has already been logged.
}
};
InternalPlatform.run(code);
}
};
accept(visitor, true);
}
public void startup(IProgressMonitor progress) {}
}