package org.eclipse.core.internal.preferences;
import java.lang.ref.WeakReference;
import java.util.*;
import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
public class PreferenceServiceRegistryHelper implements IRegistryChangeListener {
private static final String ELEMENT_INITIALIZER = "initializer";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_CLASS = "class";
private static final String ATTRIBUTE_STORAGE = "storage";
private static final String ELEMENT_SCOPE = "scope";
private static final String ELEMENT_MODIFIER = "modifier";
private final static IExtension[] EMPTY_EXTENSION_ARRAY = new IExtension[0];
private static final Map<String, Object> scopeRegistry = Collections.synchronizedMap(new HashMap<String, Object>());
private ListenerList<PreferenceModifyListener> modifyListeners;
private final PreferencesService service;
private final IExtensionRegistry registry;
private static IStatus createStatusError(String message, Exception e) {
return new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e);
}
private static IStatus createStatusWarning(String message, Exception e) {
return new Status(IStatus.WARNING, PrefsMessages.OWNER_NAME, IStatus.WARNING, message, e);
}
private static void log(IStatus status) {
RuntimeLog.log(status);
}
public PreferenceServiceRegistryHelper(PreferencesService service, Object registryObject) {
super();
this.service = service;
this.registry = (IExtensionRegistry) registryObject;
initializeScopes();
registry.addRegistryChangeListener(this);
}
void stop() {
registry.removeRegistryChangeListener(this);
}
private void addModifyListener(IConfigurationElement element) {
String key = element.getAttribute(ATTRIBUTE_CLASS);
if (key == null) {
String message = NLS.bind(PrefsMessages.preferences_missingClassAttribute, element.getDeclaringExtension().getUniqueIdentifier());
log(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, null));
return;
}
try {
Object listener = element.createExecutableExtension(ATTRIBUTE_CLASS);
if (!(listener instanceof PreferenceModifyListener)) {
log(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, PrefsMessages.preferences_classCastListener, null));
return;
}
modifyListeners.add((PreferenceModifyListener) listener);
} catch (CoreException e) {
log(e.getStatus());
}
}
public WeakReference<Object> applyRuntimeDefaults(String name, WeakReference<Object> pluginReference) {
IExtension[] extensions = getPrefExtensions();
if (extensions.length == 0) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Skipping runtime default preference customization.");
return null;
}
boolean foundInitializer = false;
for (IExtension extension : extensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
for (IConfigurationElement element : elements) {
if (ELEMENT_INITIALIZER.equals(element.getName())) {
if (name.equals(element.getContributor().getName())) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL) {
IExtension theExtension = element.getDeclaringExtension();
String extensionNamespace = theExtension.getContributor().getName();
Bundle underlyingBundle = PreferencesOSGiUtils.getDefault().getBundle(extensionNamespace);
String ownerName;
if (underlyingBundle != null)
ownerName = underlyingBundle.getSymbolicName();
else
ownerName = extensionNamespace;
PrefsMessages.message("Running default preference customization as defined by: " + ownerName);
}
runInitializer(element);
foundInitializer = true;
}
}
}
}
if (foundInitializer)
return null;
Object plugin = pluginReference.get();
ILegacyPreferences initService = PreferencesOSGiUtils.getDefault().getLegacyPreferences();
if (initService != null)
plugin = initService.init(plugin, name);
return new WeakReference<>(plugin);
}
public IEclipsePreferences createNode(RootPreferences parent, String name) {
IScope scope = null;
Object value = scopeRegistry.get(name);
if (value instanceof IConfigurationElement) {
if (((IConfigurationElement) value).getAttribute(ATTRIBUTE_CLASS) != null) {
try {
scope = (IScope) ((IConfigurationElement) value).createExecutableExtension(ATTRIBUTE_CLASS);
scopeRegistry.put(name, scope);
} catch (ClassCastException e) {
log(createStatusError(PrefsMessages.preferences_classCastScope, e));
return new EclipsePreferences(parent, name);
} catch (CoreException e) {
log(e.getStatus());
return new EclipsePreferences(parent, name);
}
} else if (((IConfigurationElement) value).getAttribute(ATTRIBUTE_STORAGE) != null) {
try {
AbstractPreferenceStorage storage = (AbstractPreferenceStorage) ((IConfigurationElement) value).createExecutableExtension(ATTRIBUTE_STORAGE);
ScopeDescriptor descriptor = new ScopeDescriptor(storage);
EclipsePreferences result = new EclipsePreferences(parent, name);
result.setDescriptor(descriptor);
return result;
} catch (ClassCastException e) {
log(createStatusError(PrefsMessages.preferences_classCastStorage, e));
return new EclipsePreferences(parent, name);
} catch (CoreException e) {
log(e.getStatus());
return new EclipsePreferences(parent, name);
}
}
} else
scope = (IScope) value;
return scope.create(parent, name);
}
public ListenerList<PreferenceModifyListener> getModifyListeners() {
if (modifyListeners == null) {
modifyListeners = new ListenerList<>();
IExtension[] extensions = getPrefExtensions();
for (IExtension extension : extensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
for (IConfigurationElement element : elements) {
if (ELEMENT_MODIFIER.equalsIgnoreCase(element.getName())) {
addModifyListener(element);
}
}
}
}
return modifyListeners;
}
private IExtension[] getPrefExtensions() {
IExtension[] extensionsOld = EMPTY_EXTENSION_ARRAY;
IExtension[] extensionsNew = EMPTY_EXTENSION_ARRAY;
IExtensionPoint pointOld = registry.getExtensionPoint(IPreferencesConstants.RUNTIME_NAME, IPreferencesConstants.PT_PREFERENCES);
if (pointOld != null)
extensionsOld = pointOld.getExtensions();
IExtensionPoint pointNew = registry.getExtensionPoint(IPreferencesConstants.PREFERS_NAME, IPreferencesConstants.PT_PREFERENCES);
if (pointNew != null)
extensionsNew = pointNew.getExtensions();
IExtension[] extensions = new IExtension[extensionsOld.length + extensionsNew.length];
System.arraycopy(extensionsOld, 0, extensions, 0, extensionsOld.length);
System.arraycopy(extensionsNew, 0, extensions, extensionsOld.length, extensionsNew.length);
if (extensions.length == 0) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("No extensions for org.eclipse.core.contenttype.");
}
return extensions;
}
private void initializeScopes() {
IExtension[] extensions = getPrefExtensions();
for (IExtension extension : extensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
for (IConfigurationElement element : elements) {
if (ELEMENT_SCOPE.equalsIgnoreCase(element.getName())) {
scopeAdded(element);
}
}
}
}
@Override
public void registryChanged(IRegistryChangeEvent event) {
IExtensionDelta[] deltasOld = event.getExtensionDeltas(IPreferencesConstants.RUNTIME_NAME, IPreferencesConstants.PT_PREFERENCES);
IExtensionDelta[] deltasNew = event.getExtensionDeltas(IPreferencesConstants.PREFERS_NAME, IPreferencesConstants.PT_PREFERENCES);
IExtensionDelta[] deltas = new IExtensionDelta[deltasOld.length + deltasNew.length];
System.arraycopy(deltasOld, 0, deltas, 0, deltasOld.length);
System.arraycopy(deltasNew, 0, deltas, deltasOld.length, deltasNew.length);
if (deltas.length == 0)
return;
for (IExtensionDelta delta : deltas) {
IConfigurationElement[] elements = delta.getExtension().getConfigurationElements();
for (IConfigurationElement element : elements) {
switch (delta.getKind()) {
case IExtensionDelta.ADDED:
if (ELEMENT_SCOPE.equalsIgnoreCase(element.getName())) {
scopeAdded(element);
}
break;
case IExtensionDelta.REMOVED:
String scope = element.getAttribute(ATTRIBUTE_NAME);
if (scope != null)
scopeRemoved(scope);
break;
}
}
}
modifyListeners = null;
}
private void runInitializer(IConfigurationElement element) {
try {
final AbstractPreferenceInitializer initializer = (AbstractPreferenceInitializer) element.createExecutableExtension(ATTRIBUTE_CLASS);
ISafeRunnable job = new ISafeRunnable() {
@Override
public void handleException(Throwable exception) {
}
@Override
public void run() throws Exception {
initializer.initializeDefaultPreferences();
}
};
SafeRunner.run(job);
} catch (ClassCastException e) {
IStatus status = new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, PrefsMessages.preferences_invalidExtensionSuperclass, e);
log(status);
} catch (CoreException e) {
log(e.getStatus());
}
}
private void scopeAdded(IConfigurationElement element) {
String key = element.getAttribute(ATTRIBUTE_NAME);
if (key == null) {
String message = NLS.bind(PrefsMessages.preferences_missingScopeAttribute, element.getDeclaringExtension().getUniqueIdentifier());
log(createStatusWarning(message, null));
return;
}
scopeRegistry.put(key, element);
((RootPreferences) service.getRootNode()).addChild(key, null);
}
private void scopeRemoved(String key) {
IEclipsePreferences node = (IEclipsePreferences) ((RootPreferences) service.getRootNode()).getNode(key, false);
if (node != null)
((RootPreferences) service.getRootNode()).removeNode(node);
else
((RootPreferences) service.getRootNode()).removeNode(key);
scopeRegistry.remove(key);
}
}