Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright (c) 2004, 2015 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
* Semion Chichelnitsky ([email protected]) - bug 208564
* Jan-Ove Weichel ([email protected]) - bug 474359
*******************************************************************************/
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;
/**
* @since 3.0
*/
public class PreferencesService implements IPreferencesService {
/**
* The interval between passes over the preference tree to canonicalize
* strings.
*/
private static final long STRING_SHARING_INTERVAL = 300000;
private static final String MATCH_TYPE_PREFIX = "prefix"; //$NON-NLS-1$
// the order of search scopes when people don't have a specific order set
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"; //$NON-NLS-1$
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static PreferencesService instance;
static final RootPreferences root = new RootPreferences();
private static final Map defaultsRegistry = Collections.synchronizedMap(new HashMap());
private Object registryHelper = null;
private final Map defaultScopes = new HashMap<>();
/**
* The last time analysis was done to remove duplicate strings
*/
private long lastStringSharing = 0;
/*
* Create and return an IStatus object with ERROR severity and the
* given message and exception.
*/
private static IStatus createStatusError(String message, Exception e) {
return new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e);
}
/*
* Return the instance.
*/
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);
// save the preferences
try {
getRootNode().node(tree.absolutePath()).flush();
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_saveProblems, e));
}
//this typically causes a major change to the preference tree, so force string sharing
lastStringSharing = 0;
shareStrings();
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
}
}
@Override
public IStatus applyPreferences(IExportedPreferences preferences) throws CoreException {
// TODO investigate refactoring to merge with new #apply(IEclipsePreferences, IPreferenceFilter[]) APIs
if (preferences == null)
throw new IllegalArgumentException();
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Applying exported preferences: " + ((ExportedPreferences) preferences).toDeepDebugString()); //$NON-NLS-1$
final MultiStatus result = new MultiStatus(PrefsMessages.OWNER_NAME, IStatus.OK, PrefsMessages.preferences_applyProblems, null);
IEclipsePreferences modifiedNode = firePreApplyEvent(preferences);
// create a visitor to apply the given set of 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;
// if this node is an export root then we need to remove
// it from the global preferences before continuing.
boolean removed = false;
if (epNode.isExportRoot()) {
if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
PrefsMessages.message("Found export root: " + epNode.absolutePath()); //$NON-NLS-1$
// TODO should only have to do this if any of my children have properties to set
globalNode.removeNode();
removed = true;
}
// iterate over the preferences in this node and set them
// in the global space.
String[] keys = epNode.properties.keys();
// if this node was removed then we need to create a new one
if (removed)
globalNode = (IEclipsePreferences) root.node(node.absolutePath());
// the list for properties to remove
List propsToRemove = new ArrayList<>();
for (String key : globalNode.keys()) {
propsToRemove.add(key);
}
if (keys.length > 0) {
String key = null;
for (String k : keys) {
key = k;
// preferences that are not in the applied node
// will be removed
propsToRemove.remove(key);
// intern strings we import because some people
// in their property change listeners use identity
// instead of equals. See bug 20193 and 20534.
key = key.intern();
String value = node.get(key, null);
if (value != null) {
if (EclipsePreferences.DEBUG_PREFERENCE_SET)
PrefsMessages.message("Setting: " + globalNode.absolutePath() + '/' + key + '=' + value); //$NON-NLS-1$
globalNode.put(key, value);
}
}
}
String keyToRemove = null;
for (Iterator it = propsToRemove.iterator(); it.hasNext();) {
keyToRemove = it.next();
keyToRemove = keyToRemove.intern();
if (EclipsePreferences.DEBUG_PREFERENCE_SET)
PrefsMessages.message("Removing: " + globalNode.absolutePath() + '/' + keyToRemove); //$NON-NLS-1$
globalNode.remove(keyToRemove);
}
// keep visiting children
return true;
}
};
try {
// start by visiting the root
modifiedNode.accept(visitor);
} catch (BackingStoreException e) {
throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
}
// save the preferences
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()); //$NON-NLS-1$
//this typically causes a major change to the preference tree, so force string sharing
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];
}
/*
* Convert the given properties file from legacy format to
* one which is Eclipse 3.0 compliant.
*
* Convert the plug-in version indicator entries to export roots.
*/
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;
}
/*
* Convert the given properties file into a node hierarchy suitable for
* importing.
*/
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()); //$NON-NLS-1$
return result;
}
/*
* excludesList is guaranteed not to be null
*/
private SortedProperties convertToProperties(IEclipsePreferences preferences, final String[] excludesList) throws BackingStoreException {
final SortedProperties result = new SortedProperties();
final int baseLength = preferences.absolutePath().length();
// create a visitor to do the export
IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
@Override
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
// don't store defaults
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));
// check the excludes list to see if this node should be considered
for (String exclude : excludesList) {
String exclusion = EclipsePreferences.makeRelative(exclude);
if (path.startsWith(exclusion))
return false;
}
boolean needToAddVersion = InstanceScope.SCOPE.equals(scope);
// check the excludes list for each preference
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;
}
};
// start by visiting the root that we were passed in
preferences.accept(visitor);
// return the properties object
return result;
}
/**
* Copy key/value pairs from the source to the destination. If the key list is null
* then copy all associations.
*
* If the depth is 0, then this operation is performed only on the source node. Otherwise
* it is performed on the source node's subtree.
*
* @param depth one of 0 or -1
*/
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