blob: a6fa6208d16fe12017290c26c364151f1abcad5b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.plugins;
import java.util.*;
import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.core.runtime.*;
import org.osgi.framework.*;
/**
* Implementation for the runtime shutdown hook that provides
* support for legacy bundles. All legacy bundles are stopped
* in the proper order.
*/
public class PluginStopper implements IShutdownHook {
private static final String OPTION_DEBUG_PLUGIN_STOPPER = "org.eclipse.core.runtime/debug/pluginstopper"; //$NON-NLS-1$
private class ReferenceKey {
private long referrerId;
private long referredId;
public ReferenceKey(long referrerId, long referredId) {
this.referrerId = referrerId;
this.referredId = referredId;
}
public boolean equals(Object obj) {
return referredId == ((ReferenceKey) obj).referredId && referrerId == ((ReferenceKey) obj).referrerId;
}
public int hashCode() {
return ((int) (referredId & 0xFFFF)) << 16 + (int) (referrerId & 0xFFFF);
}
}
public void run() {
boolean debug = InternalPlatform.getDefault().getBooleanOption(OPTION_DEBUG_PLUGIN_STOPPER,false);
BundleContext context = InternalPlatform.getDefault().getBundleContext();
Map references = new HashMap();
IPluginDescriptor[] plugins = Platform.getPluginRegistry().getPluginDescriptors();
Map activeLegacyBundles = new HashMap(plugins.length);
// gather all active legacy bundles
for (int i = 0; i < plugins.length; i++) {
if (!plugins[i].isLegacy())
continue;
Bundle pluginBundle = context.getBundle(plugins[i].getUniqueIdentifier());
if (pluginBundle.getState() == Bundle.ACTIVE) {
activeLegacyBundles.put(pluginBundle.getGlobalName(),pluginBundle);
if (debug)
System.out.println("Active plugin bundle: " + pluginBundle.getGlobalName()); //$NON-NLS-1$
}
}
// find dependencies betweeen them
for (Iterator pluginBundlesIter = activeLegacyBundles.values().iterator(); pluginBundlesIter.hasNext();) {
Bundle pluginBundle = (Bundle) pluginBundlesIter.next();
// TODO eliminate this reference to getHeaders
Dictionary headers = pluginBundle.getHeaders();
String requireBundleNames = (String) headers.get(Constants.REQUIRE_BUNDLE);
if (requireBundleNames == null)
// no Require-Bundle entry - does not depend on other legacy bundles
continue;
StringTokenizer tokenizer = new StringTokenizer(requireBundleNames," ,\t\n\r\f");
while(tokenizer.hasMoreTokens()) {
String importedBundleName = tokenizer.nextToken();
Bundle importedBundle = (Bundle) activeLegacyBundles.get(importedBundleName);
// ignore dependencies on non-active legacy bundles
if (importedBundle == null)
continue;
references.put(new ReferenceKey(pluginBundle.getBundleId(),importedBundle.getBundleId()), new Object[] { pluginBundle, importedBundle });
}
}
Bundle[] orderedBundles = (Bundle[]) activeLegacyBundles.values().toArray(new Bundle[activeLegacyBundles.size()]);
Object[][] cycles = ComputeNodeOrder.computeNodeOrder(orderedBundles, (Object[][]) references.values().toArray(new Object[references.size()][]));
if (debug) {
for (int i = 0; i < cycles.length; i++) {
StringBuffer sb = new StringBuffer("***Cycle: "); //$NON-NLS-1$
for (int j = 0; j < cycles[i].length; j++) {
sb.append('\n');
sb.append(((Bundle)cycles[i][j]).getGlobalName());
}
System.out.println(sb);
}
for (Iterator iter = references.values().iterator(); iter.hasNext();) {
Object[] ref = (Object[]) iter.next();
System.out.println(ref[0].toString() + " -> " + ref[1]); //$NON-NLS-1$
}
}
// stop all active legacy bundles in the reverse order of Require-Bundle
for (int i = orderedBundles.length - 1; i >= 0; i--) {
try {
if (Platform.getPluginRegistry().getPluginDescriptor(orderedBundles[i].getGlobalName()).isLegacy() && orderedBundles[i].getState() == Bundle.ACTIVE) {
if (debug)
System.out.println("Stopping: " + orderedBundles[i].getGlobalName() + " (#" + orderedBundles[i].getBundleId() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
orderedBundles[i].stop();
}
} catch (Exception e) {
String message = Policy.bind("activator.errorStoppingPlugin",orderedBundles[i].toString()); //$NON-NLS-1$
IStatus status = new Status(IStatus.ERROR, IPlatform.PI_RUNTIME_COMPATIBILITY, 1, message, e);
InternalPlatform.getDefault().log(status);
}
}
}
}