package org.eclipse.core.internal.preferences;
import java.io.*;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
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;
import org.osgi.framework.Constants;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
public class PreferencesService implements IPreferencesService {
private static final long STRING_SHARING_INTERVAL = 300000;
private static final String MATCH_TYPE_PREFIX = "prefix";
private static String[] DEFAULT_DEFAULT_LOOKUP_ORDER = new String[] {
InstanceScope.SCOPE,
ConfigurationScope.SCOPE,
DefaultScope.SCOPE};
private static final char EXPORT_ROOT_PREFIX = '!';
private static final char BUNDLE_VERSION_PREFIX = '@';
private static final float EXPORT_VERSION = 3;
private static final String VERSION_KEY = "file_export_version";
private static final String EMPTY_STRING = "";
private static PreferencesService instance;
static final RootPreferences root = new RootPreferences();
private static final Map<String, LookupOrder> defaultsRegistry = Collections.synchronizedMap(new HashMap<String, LookupOrder>());
private Object registryHelper = null;
private final Map<String, EclipsePreferences> defaultScopes = new HashMap<>();
private long lastStringSharing = 0;
private static IStatus createStatusError(String message, Exception e) {
return new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e);
}
public static PreferencesService getDefault() {
if (instance == null)
instance = new PreferencesService();
return instance;
}
static void log(IStatus status) {
RuntimeLog.log(status);
}
PreferencesService() {
super();
initializeDefaultScopes();
}
@Override
public void applyPreferences(IEclipsePreferences tree, IPreferenceFilter[] filters) throws CoreException {
if (filters == null || filters.length == 0)
return;
try {
internalApply(tree, filters);
try {
getRootNode().node(tree.absolutePath()).flush();
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_saveProblems, e));
}
lastStringSharing = 0;
shareStrings();
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
}
}
@Override
public IStatus applyPreferences(IExportedPreferences preferences) throws CoreException {
if (preferences == null)
throw new IllegalArgumentException();
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Applying exported preferences: " + ((ExportedPreferences) preferences).toDeepDebugString());
final MultiStatus result = new MultiStatus(PrefsMessages.OWNER_NAME, IStatus.OK, PrefsMessages.preferences_applyProblems, null);
IEclipsePreferences modifiedNode = firePreApplyEvent(preferences);
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
IEclipsePreferences globalNode;
if (node.parent() == null)
globalNode = root;
else
globalNode = (IEclipsePreferences) root.node(node.absolutePath());
ExportedPreferences epNode = (ExportedPreferences) node;
boolean removed = false;
if (epNode.isExportRoot()) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Found export root: " + epNode.absolutePath());
globalNode.removeNode();
removed = true;
}
String[] keys = epNode.properties.keys();
if (removed)
globalNode = (IEclipsePreferences) root.node(node.absolutePath());
List<String> propsToRemove = new ArrayList<>();
for (String key : globalNode.keys()) {
propsToRemove.add(key);
}
if (keys.length > 0) {
String key = null;
for (String k : keys) {
key = k;
propsToRemove.remove(key);
key = key.intern();
String value = node.get(key, null);
if (value != null) {
if (EclipsePreferences.DEBUG_PREFERENCE_SET)
PrefsMessages.message("Setting: " + globalNode.absolutePath() + '/' + key + '=' + value);
globalNode.put(key, value);
}
}
}
String keyToRemove = null;
for (Iterator<String> it = propsToRemove.iterator(); it.hasNext();) {
keyToRemove = it.next();
keyToRemove = keyToRemove.intern();
if (EclipsePreferences.DEBUG_PREFERENCE_SET)
PrefsMessages.message("Removing: " + globalNode.absolutePath() + '/' + keyToRemove);
globalNode.remove(keyToRemove);
}
return true;
}
};
try {
modifiedNode.accept(visitor);
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
}
try {
getRootNode().node(modifiedNode.absolutePath()).flush();
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_saveProblems, e));
}
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Current list of all settings: " + ((EclipsePreferences) getRootNode()).toDeepDebugString());
lastStringSharing = 0;
shareStrings();
return result;
}
private boolean containsKeys(IEclipsePreferences aRoot) throws BackingStoreException {
final boolean result[] = new boolean[] {false};
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
if (node.keys().length != 0)
result[0] = true;
return !result[0];
}
};
aRoot.accept(visitor);
return result[0];
}
private Properties convertFromLegacy(Properties properties) {
Properties result = new Properties();
String prefix = IPath.SEPARATOR + InstanceScope.SCOPE + IPath.SEPARATOR;
for (Entry<?, ?> entry : properties.entrySet()) {
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (value != null) {
int index = key.indexOf(IPath.SEPARATOR);
if (index == -1) {
result.put(BUNDLE_VERSION_PREFIX + key, value);
result.put(EXPORT_ROOT_PREFIX + prefix + key, EMPTY_STRING);
} else {
String path = key.substring(0, index);
key = key.substring(index + 1);
result.put(EclipsePreferences.encodePath(prefix + path, key), value);
}
}
}
return result;
}
private IExportedPreferences convertFromProperties(Properties properties) {
IExportedPreferences result = ExportedPreferences.newRoot();
for (Entry<?, ?> entry : properties.entrySet()) {
String path = (String) entry.getKey();
String value = (String) entry.getValue();
if (path.charAt(0) == EXPORT_ROOT_PREFIX) {
ExportedPreferences current = (ExportedPreferences) result.node(path.substring(1));
current.setExportRoot();
} else if (path.charAt(0) == BUNDLE_VERSION_PREFIX) {
ExportedPreferences current = (ExportedPreferences) result.node(InstanceScope.SCOPE).node(path.substring(1));
current.setVersion(value);
} else {
String[] decoded = EclipsePreferences.decodePath(path);
path = decoded[0] == null ? EMPTY_STRING : decoded[0];
ExportedPreferences current = (ExportedPreferences) result.node(path);
String key = decoded[1];
current.put(key, value);
}
}
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Converted preferences file to IExportedPreferences tree: " + ((ExportedPreferences) result).toDeepDebugString());
return result;
}
private SortedProperties convertToProperties(IEclipsePreferences preferences, final String[] excludesList) throws BackingStoreException {
final SortedProperties result = new SortedProperties();
final int baseLength = preferences.absolutePath().length();
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
String absolutePath = node.absolutePath();
String scope = getScope(absolutePath);
if (DefaultScope.SCOPE.equals(scope))
return false;
String path = absolutePath.length() <= baseLength ? EMPTY_STRING : EclipsePreferences.makeRelative(absolutePath.substring(baseLength));
for (String exclude : excludesList) {
String exclusion = EclipsePreferences.makeRelative(exclude);
if (path.startsWith(exclusion))
return false;
}
boolean needToAddVersion = InstanceScope.SCOPE.equals(scope);
String[] keys = node.keys();
for (String key : keys) {
boolean ignore = false;
for (int j = 0; !ignore && j < excludesList.length; j++)
if (EclipsePreferences.encodePath(path, key).startsWith(EclipsePreferences.makeRelative(excludesList[j])))
ignore = true;
if (!ignore) {
String value = node.get(key, null);
if (value != null) {
if (needToAddVersion) {
String bundle = getBundleName(absolutePath);
if (bundle != null) {
String version = getBundleVersion(bundle);
if (version != null)
result.put(BUNDLE_VERSION_PREFIX + bundle, version);
}
needToAddVersion = false;
}
result.put(EclipsePreferences.encodePath(absolutePath, key), value);
}
}
}
return true;
}
};
preferences.accept(visitor);
return result;
}
void copyFromTo(Preferences source, Preferences destination, String[] keys, int depth) throws BackingStoreException {
String[] keysToCopy = keys == null ? source.keys() : keys;
for (String key : keysToCopy) {
String value = source.get(key, null);
if (value != null) {
destination.put(key, value);
}
}
if (depth == 0)
return;
String[] children = source.childrenNames();
for (String child : children) {
copyFromTo(source.node(child), destination.node(child), keys, depth);
}
}
public WeakReference<Object> applyRuntimeDefaults(String name, WeakReference<Object> pluginReference) {
if (registryHelper == null)
return null;
return ((PreferenceServiceRegistryHelper) registryHelper).applyRuntimeDefaults(name, pluginReference);
}
private void initializeDefaultScopes() {
defaultScopes.put(BundleDefaultsScope.SCOPE, new BundleDefaultPreferences());
root.addChild(BundleDefaultsScope.SCOPE, null);
defaultScopes.put(DefaultScope.SCOPE, new DefaultPreferences());
root.addChild(DefaultScope.SCOPE, null);
defaultScopes.put(InstanceScope.SCOPE, new InstancePreferences());
root.addChild(InstanceScope.SCOPE, null);
defaultScopes.put(ConfigurationScope.SCOPE, new ConfigurationPreferences());
root.addChild(ConfigurationScope.SCOPE, null);
}
public IEclipsePreferences createNode(String key) {
IScope scope = defaultScopes.get(key);
if (scope == null) {
if (registryHelper == null)
return new EclipsePreferences(root, key);
return ((PreferenceServiceRegistryHelper) registryHelper).createNode(root, key);
}
return scope.create(root, key);
}
@Override
public void exportPreferences(IEclipsePreferences node, IPreferenceFilter[] filters, OutputStream stream) throws CoreException {
if (filters == null || filters.length == 0)
return;
try {
internalExport(node, filters, stream);
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_exportProblems, e));
}
}
@Override
public IStatus exportPreferences(IEclipsePreferences node, OutputStream output, String[] excludesList) throws CoreException {
if (node == null || output == null)
throw new IllegalArgumentException();
SortedProperties properties = null;
if (excludesList == null)
excludesList = new String[0];
try {
properties = convertToProperties(node, excludesList);
if (properties.isEmpty())
return Status.OK_STATUS;
properties.put(VERSION_KEY, Float.toString(EXPORT_VERSION));
properties.put(EXPORT_ROOT_PREFIX + node.absolutePath(), EMPTY_STRING);
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(e.getMessage(), e));
}
try {
properties.store(output, null);
} catch (IOException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_exportProblems, e));
}
return Status.OK_STATUS;
}
private IEclipsePreferences firePreApplyEvent(IEclipsePreferences tree) {
if (registryHelper == null)
return tree;
final IEclipsePreferences[] result = new IEclipsePreferences[] {tree};
ListenerList<PreferenceModifyListener> listeners = ((PreferenceServiceRegistryHelper) registryHelper).getModifyListeners();
for (final PreferenceModifyListener listener : listeners) {
ISafeRunnable job = new ISafeRunnable() {
@Override
public void handleException(Throwable exception) {
}
@Override
public void run() throws Exception {
result[0] = listener.preApply(result[0]);
}
};
SafeRunner.run(job);
}
return result[0];
}
@Override
public String get(String key, String defaultValue, Preferences[] nodes) {
if (nodes == null)
return defaultValue;
for (Preferences node : nodes) {
if (node != null) {
String result = node.get(key, null);
if (result != null)
return result;
}
}
return defaultValue;
}
@Override
public boolean getBoolean(String qualifier, String key, boolean defaultValue, IScopeContext[] scopes) {
String result = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
return result == null ? defaultValue : Boolean.valueOf(result).booleanValue();
}
String getBundleName(String path) {
if (path.length() == 0 || path.charAt(0) != IPath.SEPARATOR)
return null;
int first = path.indexOf(IPath.SEPARATOR, 1);
if (first == -1)
return null;
int second = path.indexOf(IPath.SEPARATOR, first + 1);
return second == -1 ? path.substring(first + 1) : path.substring(first + 1, second);
}
String getBundleVersion(String bundleName) {
Bundle bundle = PreferencesOSGiUtils.getDefault().getBundle(bundleName);
if (bundle != null) {
Object version = bundle.getHeaders(EMPTY_STRING).get(Constants.BUNDLE_VERSION);
if (version != null && version instanceof String)
return (String) version;
}
return null;
}
@Override
public byte[] getByteArray(String qualifier, String key, byte[] defaultValue, IScopeContext[] scopes) {
String result = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
return result == null ? defaultValue : Base64.decode(result.getBytes());
}
@Override
public String[] getDefaultLookupOrder(String qualifier, String key) {
LookupOrder order = defaultsRegistry.get(getRegistryKey(qualifier, key));
return order == null ? null : order.getOrder();
}
@Override
public double getDouble(String qualifier, String key, double defaultValue, IScopeContext[] scopes) {
String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
if (value == null)
return defaultValue;
try {
return Double.parseDouble(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}
@Override
public float getFloat(String qualifier, String key, float defaultValue, IScopeContext[] scopes) {
String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
if (value == null)
return defaultValue;
try {
return Float.parseFloat(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}
@Override
public int getInt(String qualifier, String key, int defaultValue, IScopeContext[] scopes) {
String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
if (value == null)
return defaultValue;
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}
@Override
public long getLong(String qualifier, String key, long defaultValue, IScopeContext[] scopes) {
String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
if (value == null)
return defaultValue;
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}
@Override
public String[] getLookupOrder(String qualifier, String key) {
String[] order = getDefaultLookupOrder(qualifier, key);
if (order == null && key != null)
order = getDefaultLookupOrder(qualifier, null);
if (order == null)
order = DEFAULT_DEFAULT_LOOKUP_ORDER;
return order;
}
private Preferences[] getNodes(final String qualifier, String key, final IScopeContext[] contexts) {
String[] order = getLookupOrder(qualifier, key);
final String childPath = EclipsePreferences.makeRelative(EclipsePreferences.decodePath(key)[0]);
final ArrayList<Preferences> result = new ArrayList<>();
for (String scopeString : order) {
AtomicReference<IllegalStateException> error = new AtomicReference<>();
SafeRunner.run(new ISafeRunnable() {
private IScopeContext context;
@Override
public void run() throws Exception {
boolean found = false;
for (int j = 0; contexts != null && j < contexts.length; j++) {
context = contexts[j];
if (context != null && context.getName().equals(scopeString)) {
Preferences node = context.getNode(qualifier);
if (node != null) {
found = true;
if (childPath != null)
node = node.node(childPath);
result.add(node);
}
}
}
if (!found) {
Preferences node = getRootNode().node(scopeString).node(qualifier);
if (childPath != null)
node = node.node(childPath);
result.add(node);
}
found = false;
}
@Override
public void handleException(Throwable exception) {
if (context instanceof InstanceScope && exception instanceof IllegalStateException && Boolean.getBoolean("osgi.dataAreaRequiresExplicitInit")) {
error.set((IllegalStateException) exception);
} else {
log(new Status(IStatus.ERROR, Activator.PI_PREFERENCES, PrefsMessages.preferences_contextError, exception));
}
}
});
IllegalStateException illegalState = error.get();
if (illegalState != null) {
throw illegalState;
}
}
return result.toArray(new Preferences[result.size()]);
}
private String getRegistryKey(String qualifier, String key) {
if (qualifier == null)
throw new IllegalArgumentException();
if (key == null)
return qualifier;
return qualifier + '/' + key;
}
@Override
public IEclipsePreferences getRootNode() {
return root;
}
String getScope(String path) {
if (path == null || path.length() == 0)
return EMPTY_STRING;
int startIndex = path.indexOf(IPath.SEPARATOR);
if (startIndex == -1)
return path;
if (path.length() == 1)
return EMPTY_STRING;
int endIndex = path.indexOf(IPath.SEPARATOR, startIndex + 1);
if (endIndex == -1)
endIndex = path.length();
return path.substring(startIndex + 1, endIndex);
}
@Override
public String getString(String qualifier, String key, String defaultValue, IScopeContext[] scopes) {
return get(EclipsePreferences.decodePath(key)[1], defaultValue, getNodes(qualifier, key, scopes));
}
@Override
public IStatus importPreferences(InputStream input) throws CoreException {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Importing preferences...");
return applyPreferences(readPreferences(input));
}
private void internalApply(IEclipsePreferences tree, IPreferenceFilter[] filters) throws BackingStoreException {
ArrayList<IEclipsePreferences> trees = new ArrayList<>();
for (IPreferenceFilter filter : filters) {
trees.add(trimTree(tree, filter));
}
IEclipsePreferences toApply = mergeTrees(trees.toArray(new IEclipsePreferences[trees.size()]));
toApply = firePreApplyEvent(toApply);
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
String[] keys = node.keys();
if (keys.length == 0)
return true;
copyFromTo(node, getRootNode().node(node.absolutePath()), keys, 0);
return true;
}
};
toApply.accept(visitor);
}
private void internalExport(IEclipsePreferences node, IPreferenceFilter filters[], OutputStream output) throws BackingStoreException, CoreException {
ArrayList<IEclipsePreferences> trees = new ArrayList<>();
for (IPreferenceFilter filter : filters) {
trees.add(trimTree(node, filter));
}
IEclipsePreferences toExport = mergeTrees(trees.toArray(new IEclipsePreferences[trees.size()]));
exportPreferences(toExport, output, (String[]) null);
}
private boolean internalMatches(IEclipsePreferences tree, IPreferenceFilter filter) throws BackingStoreException {
String[] scopes = filter.getScopes();
if (scopes == null)
throw new IllegalArgumentException();
String treePath = tree.absolutePath();
for (String scope : scopes) {
Map<String, PreferenceFilterEntry[]> mapping = filter.getMapping(scope);
if (mapping == null) {
if (tree.parent() == null && tree.nodeExists(scope)) {
if (containsKeys((IEclipsePreferences) tree.node(scope)))
return true;
}
if (scopeMatches(scope, tree) && containsKeys(tree))
return true;
continue;
}
for (String nodePath : mapping.keySet()) {
String nodeFullPath = '/' + scope + '/' + nodePath;
if (!nodeFullPath.startsWith(treePath))
continue;
String childPath = nodeFullPath.substring(treePath.length());
childPath = EclipsePreferences.makeRelative(childPath);
if (tree.nodeExists(childPath)) {
PreferenceFilterEntry[] entries;
try {
entries = mapping.get(nodePath);
} catch (ClassCastException e) {
log(createStatusError(PrefsMessages.preferences_classCastFilterEntry, e));
continue;
}
Preferences child = tree.node(childPath);
if (entries == null) {
if (child.keys().length != 0 || child.childrenNames().length != 0)
return true;
} else {
for (PreferenceFilterEntry entry : entries) {
if (entry == null) {
continue;
}
if (entry.getMatchType() == null) {
if (child.get(entry.getKey(), null) != null) {
return true;
}
} else if (internalMatchesWithMatchType(entry, child.keys())) {
return true;
}
}
}
}
}
}
return false;
}
private IPreferenceFilter[] internalMatches(IEclipsePreferences tree, IPreferenceFilter[] filters) throws BackingStoreException {
ArrayList<IPreferenceFilter> result = new ArrayList<>();
for (IPreferenceFilter filter : filters) {
if (internalMatches(tree, filter)) {
result.add(filter);
}
}
return result.toArray(new IPreferenceFilter[result.size()]);
}
private boolean internalMatchesWithMatchType(PreferenceFilterEntry entry, String[] keys) {
if (keys == null || keys.length == 0)
return false;
String key = entry.getKey();
String matchType = entry.getMatchType();
if (!matchType.equalsIgnoreCase(MATCH_TYPE_PREFIX))
return false;
for (String k : keys) {
if (k.startsWith(key)) {
return true;
}
}
return false;
}
private boolean isLegacy(Properties properties) {
return properties.getProperty(VERSION_KEY) == null;
}
@Override
public IPreferenceFilter[] matches(IEclipsePreferences tree, IPreferenceFilter[] filters) throws CoreException {
if (filters == null || filters.length == 0)
return new IPreferenceFilter[0];
try {
return internalMatches(tree, filters);
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_matching, e));
}
}
private IEclipsePreferences mergeTrees(IEclipsePreferences[] trees) throws BackingStoreException {
if (trees.length == 1)
return trees[0];
final IEclipsePreferences result = ExportedPreferences.newRoot();
if (trees.length == 0)
return result;
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
Preferences destination = result.node(node.absolutePath());
copyFromTo(node, destination, null, 0);
return true;
}
};
for (IEclipsePreferences tree : trees) {
tree.accept(visitor);
}
return result;
}
@Override
public IExportedPreferences readPreferences(InputStream input) throws CoreException {
if (input == null)
throw new IllegalArgumentException();
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Reading preferences from stream...");
Properties properties = new Properties();
try {
properties.load(input);
} catch (IOException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_importProblems, e));
} catch (IllegalArgumentException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_importProblems, e));
} finally {
try {
input.close();
} catch (IOException e) {
}
}
if (properties.isEmpty())
throw new CoreException(createStatusError(PrefsMessages.preferences_invalidFileFormat, null));
if (isLegacy(properties)) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Read legacy preferences file, converting to 3.0 format...");
properties = convertFromLegacy(properties);
} else {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Read preferences file.");
properties.remove(VERSION_KEY);
}
return convertFromProperties(properties);
}
private boolean scopeMatches(String scope, IEclipsePreferences tree) {
if (tree.parent() == null)
return false;
String path = tree.absolutePath();
int index = path.indexOf('/', 1);
String sub = path.substring(1, index == -1 ? path.length() : index);
return scope.equals(sub);
}
@Override
public void setDefaultLookupOrder(String qualifier, String key, String[] order) {
String registryKey = getRegistryKey(qualifier, key);
if (order == null)
defaultsRegistry.remove(registryKey);
else {
LookupOrder obj = new LookupOrder(order);
defaultsRegistry.put(registryKey, obj);
}
}
public void setRegistryHelper(Object registryHelper) {
if (this.registryHelper != null && this.registryHelper != registryHelper)
((PreferenceServiceRegistryHelper) this.registryHelper).stop();
this.registryHelper = registryHelper;
}
void shareStrings() {
long now = System.currentTimeMillis();
if (now - lastStringSharing < STRING_SHARING_INTERVAL)
return;
StringPool pool = new StringPool();
root.shareStrings(pool);
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
System.out.println("Preference string sharing saved: " + pool.getSavedStringCount());
lastStringSharing = now;
}
private IEclipsePreferences trimTree(IEclipsePreferences tree, IPreferenceFilter filter) throws BackingStoreException {
IEclipsePreferences result = (IEclipsePreferences) ExportedPreferences.newRoot().node(tree.absolutePath());
String[] scopes = filter.getScopes();
if (scopes == null)
throw new IllegalArgumentException();
String treePath = tree.absolutePath();
for (String scope : scopes) {
Map<String, PreferenceFilterEntry[]> mapping = filter.getMapping(scope);
if (mapping == null) {
if (tree.parent() == null && tree.nodeExists(scope))
copyFromTo(tree.node(scope), result.node(scope), null, -1);
else if (scopeMatches(scope, tree))
copyFromTo(tree, result, null, -1);
continue;
}
for (String nodePath : mapping.keySet()) {
String nodeFullPath = '/' + scope + '/' + nodePath;
if (!nodeFullPath.startsWith(treePath))
continue;
String childPath = nodeFullPath.substring(treePath.length());
childPath = EclipsePreferences.makeRelative(childPath);
if (tree.nodeExists(childPath)) {
Preferences child = tree.node(childPath);
PreferenceFilterEntry[] entries;
try {
entries = mapping.get(nodePath);
} catch (ClassCastException e) {
log(createStatusError(PrefsMessages.preferences_classCastFilterEntry, e));
continue;
}
String[] keys = null;
if (entries != null) {
ArrayList<String> list = new ArrayList<>();
for (PreferenceFilterEntry entry : entries) {
if (entry != null) {
addMatchedKeys(list, entry, child.keys());
}
}
keys = list.toArray(new String[list.size()]);
}
copyFromTo(tree.node(childPath), result.node(childPath), keys, keys == null ? -1 : 0);
}
}
}
return result;
}
private void addMatchedKeys(ArrayList<String> list, PreferenceFilterEntry entry, String[] keys) {
String matchType = entry.getMatchType();
if (matchType == null) {
list.add(entry.getKey());
return;
}
if (keys == null)
return;
String key = entry.getKey();
for (String k : keys) {
if (matchType.equals(MATCH_TYPE_PREFIX) && k.startsWith(key)) {
list.add(k);
}
}
}
IStatus validatePluginVersions(String bundle, PluginVersionIdentifier pref, PluginVersionIdentifier installed) {
if (installed.getMajorComponent() == pref.getMajorComponent() && installed.getMinorComponent() == pref.getMinorComponent())
return null;
int severity;
if (installed.getMajorComponent() < pref.getMajorComponent())
severity = IStatus.ERROR;
else
severity = IStatus.WARNING;
String msg = NLS.bind(PrefsMessages.preferences_incompatible, (new Object[] {pref, bundle, installed}));
return new Status(severity, PrefsMessages.OWNER_NAME, 1, msg, null);
}
public IStatus validateVersions(IPath path) {
final MultiStatus result = new MultiStatus(PrefsMessages.OWNER_NAME, IStatus.INFO, PrefsMessages.preferences_validate, null);
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) {
if (!(node instanceof ExportedPreferences))
return false;
ExportedPreferences realNode = (ExportedPreferences) node;
String version = realNode.getVersion();
if (version == null || !PluginVersionIdentifier.validateVersion(version).isOK())
return true;
PluginVersionIdentifier versionInFile = new PluginVersionIdentifier(version);
String bundleName = getBundleName(node.absolutePath());
if (bundleName == null)
return true;
String stringVersion = getBundleVersion(bundleName);
if (stringVersion == null || !PluginVersionIdentifier.validateVersion(stringVersion).isOK())
return true;
PluginVersionIdentifier versionInMemory = new PluginVersionIdentifier(stringVersion);
IStatus verification = validatePluginVersions(bundleName, versionInFile, versionInMemory);
if (verification != null)
result.add(verification);
return true;
}
};
InputStream input = null;
try {
input = new BufferedInputStream(new FileInputStream(path.toFile()));
IExportedPreferences prefs = readPreferences(input);
prefs.accept(visitor);
} catch (FileNotFoundException e) {
} catch (CoreException e) {
result.add(createStatusError(PrefsMessages.preferences_validationException, e));
} catch (BackingStoreException e) {
result.add(createStatusError(PrefsMessages.preferences_validationException, e));
}
return result;
}
public String[] getDefaultDefaultLookupOrder() {
return DEFAULT_DEFAULT_LOOKUP_ORDER;
}
public void setDefaultDefaultLookupOrder(String[] order) {
if (order == null)
order = new String[0];
DEFAULT_DEFAULT_LOOKUP_ORDER = order;
}
}