blob: 6238a7ae1aa851e78d2dd26cdfc5ab6453f5ca67 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 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
* Danail Nachev - bug 203599 - events if jobs bundle has been stopped
*******************************************************************************/
package org.eclipse.core.internal.registry.osgi;
import java.io.File;
import java.util.Map;
import org.eclipse.core.internal.registry.RegistryMessages;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* The registry strategy used by the Equinox extension registry. Adds to the
* OSGi registry:
* <p><ul>
* <li>Use debug information supplied via .options files</li>
* <li>Use Eclipse logging - Use Eclipse platform state for cache validation</li>
* <li>Event scheduling is done using Eclipse job scheduling mechanism</li>
* </ul></p>
*
* @since org.eclipse.equinox.registry 3.2
*/
public class EquinoxRegistryStrategy extends RegistryStrategyOSGI {
public static final String PLUGIN_NAME = "org.eclipse.equinox.registry"; //$NON-NLS-1$
public static final String OPTION_DEBUG = PLUGIN_NAME + "/debug"; //$NON-NLS-1$
public static final String OPTION_DEBUG_EVENTS = PLUGIN_NAME + "/debug/events"; //$NON-NLS-1$
private static boolean DEBUG_ECLIPSE_REGISTRY = OSGIUtils.getDefault().getBooleanDebugOption(OPTION_DEBUG, false);
private static boolean DEBUG_ECLIPSE_EVENTS = OSGIUtils.getDefault().getBooleanDebugOption(OPTION_DEBUG_EVENTS, false);
private boolean useJobs = true;
public EquinoxRegistryStrategy(File[] theStorageDir, boolean[] cacheReadOnly, Object key) {
super(theStorageDir, cacheReadOnly, key);
}
@Override
public boolean debug() {
return DEBUG_ECLIPSE_REGISTRY;
}
@Override
public boolean debugRegistryEvents() {
return DEBUG_ECLIPSE_EVENTS;
}
@Override
public final void log(IStatus status) {
RuntimeLog.log(status);
}
@Override
public long getContainerTimestamp() {
BundleContext context = Activator.getContext();
if (context == null) {
RuntimeLog.log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.bundle_not_activated, null));
return -1;
}
// use a string here instead of the class to prevent class loading.
ServiceReference<?> ref = context.getServiceReference("org.eclipse.osgi.service.resolver.PlatformAdmin"); //$NON-NLS-1$
if (ref == null)
return -1;
return EquinoxUtils.getContainerTimestamp(context, ref);
}
/**
* This method will attempt to use Eclipse Jobs mechanism to schedule registry events. If, at any time,
* Eclipse Jobs mechanism is missing, this method will fallback on the "internal" event scheduling
* provided by the registry strategy.
*
* Once the switch to the fallback mechanism occurred, no further attempt to use scheduling from the Jobs bundle
* will be made (until registry bundle is restarted). Avoiding repeated checks in this scenario will ensure that
* most users see no performance degradation and that order of registry events remains consistent.
*/
@Override
public final void scheduleChangeEvent(Object[] listeners, Map<String, ?> deltas, Object registry) {
if (useJobs) {
try {
new ExtensionEventDispatcherJob(listeners, deltas, registry).schedule();
return; // all done - most typical use case
} catch (NoClassDefFoundError | IllegalStateException e) {
useJobs = false;
// Jobs are missing or
// Jobs bundles was stopped
}
}
super.scheduleChangeEvent(listeners, deltas, registry);
}
}