| /******************************************************************************* |
| * Copyright (c) 2004 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.preferences; |
| |
| import java.io.*; |
| import java.util.*; |
| import org.eclipse.core.internal.runtime.InternalPlatform; |
| import org.eclipse.core.internal.runtime.Policy; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.core.runtime.preferences.*; |
| 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, IRegistryChangeListener { |
| |
| // cheat here and add "project" even though we really shouldn't know about it |
| // because of plug-in dependancies and it being defined in the resources plug-in |
| private static final String[] DEFAULT_DEFAULT_LOOKUP_ORDER = new String[] {"project", //$NON-NLS-1$ |
| 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 ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$ |
| private static final String ELEMENT_SCOPE = "scope"; //$NON-NLS-1$ |
| private static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| |
| private static IPreferencesService instance; |
| static final RootPreferences root = new RootPreferences(); |
| private static final Map defaultsRegistry = Collections.synchronizedMap(new HashMap()); |
| private static final Map scopeRegistry = Collections.synchronizedMap(new HashMap()); |
| |
| /* |
| * 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, Platform.PI_RUNTIME, IStatus.ERROR, message, e); |
| } |
| |
| /* |
| * Create and return an IStatus object with WARNING severity and the |
| * given message and exception. |
| */ |
| private static IStatus createStatusWarning(String message, Exception e) { |
| return new Status(IStatus.WARNING, Platform.PI_RUNTIME, IStatus.WARNING, message, e); |
| } |
| |
| /* |
| * Return the instance. |
| */ |
| public static IPreferencesService getDefault() { |
| if (instance == null) |
| instance = new PreferencesService(); |
| return instance; |
| } |
| |
| /** |
| * See who is plugged into the extension point. |
| */ |
| private void initializeScopes() { |
| IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Platform.PI_RUNTIME, Platform.PT_PREFERENCES); |
| if (point == null) |
| return; |
| IExtension[] extensions = point.getExtensions(); |
| for (int i = 0; i < extensions.length; i++) { |
| IConfigurationElement[] elements = extensions[i].getConfigurationElements(); |
| for (int j = 0; j < elements.length; j++) |
| if (ELEMENT_SCOPE.equalsIgnoreCase(elements[j].getName())) |
| scopeAdded(elements[j]); |
| } |
| Platform.getExtensionRegistry().addRegistryChangeListener(this, Platform.PI_RUNTIME); |
| } |
| |
| static void log(IStatus status) { |
| InternalPlatform.getDefault().log(status); |
| } |
| |
| /* |
| * Abstracted into a separate method to prepare for dynamic awareness. |
| */ |
| static void scopeAdded(IConfigurationElement element) { |
| String key = element.getAttribute(ATTRIBUTE_NAME); |
| if (key == null) { |
| String message = Policy.bind("preferences.missingScopeAttribute", element.getDeclaringExtension().getUniqueIdentifier()); //$NON-NLS-1$ |
| log(createStatusWarning(message, null)); |
| return; |
| } |
| scopeRegistry.put(key, element); |
| root.addChild(key, null); |
| } |
| |
| /* |
| * Abstracted into a separate method to prepare for dynamic awareness. |
| */ |
| static void scopeRemoved(String key) { |
| IEclipsePreferences node = (IEclipsePreferences) root.node(key); |
| root.removeNode(node); |
| scopeRegistry.remove(key); |
| } |
| |
| private PreferencesService() { |
| super(); |
| initializeScopes(); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#applyPreferences(org.eclipse.core.runtime.preferences.IExportedPreferences) |
| */ |
| public IStatus applyPreferences(IExportedPreferences preferences) throws CoreException { |
| if (preferences == null) |
| throw new IllegalArgumentException(); |
| |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Applying exported preferences: " + ((ExportedPreferences) preferences).toDeepDebugString()); //$NON-NLS-1$ |
| |
| final MultiStatus result = new MultiStatus(Platform.PI_RUNTIME, IStatus.OK, Policy.bind("preferences.applyProblems"), null); //$NON-NLS-1$ |
| |
| // create a visitor to apply the given set of preferences |
| IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() { |
| 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 (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("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. |
| if (epNode.properties != null && !epNode.properties.isEmpty()) { |
| // if this node was removed then we need to create a new one |
| if (removed) |
| globalNode = (IEclipsePreferences) root.node(node.absolutePath()); |
| for (Iterator i = epNode.properties.keySet().iterator(); i.hasNext();) { |
| String key = (String) i.next(); |
| // 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 (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Setting: " + globalNode.absolutePath() + '/' + key + '=' + value); //$NON-NLS-1$ |
| globalNode.put(key, value); |
| } |
| } |
| } |
| |
| // keep visiting children |
| return true; |
| } |
| }; |
| |
| try { |
| // start by visiting the root |
| preferences.accept(visitor); |
| } catch (BackingStoreException e) { |
| String message = Policy.bind("preferences.applyProblems"); //$NON-NLS-1$ |
| throw new CoreException(createStatusError(message, e)); |
| } |
| |
| // save the prefs |
| try { |
| getRootNode().node(preferences.absolutePath()).flush(); |
| } catch (BackingStoreException e) { |
| String message = Policy.bind("preferences.saveProblems"); //$NON-NLS-1$ |
| throw new CoreException(createStatusError(message, e)); |
| } |
| |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Current list of all settings: " + ((EclipsePreferences) getRootNode()).toDeepDebugString()); //$NON-NLS-1$ |
| |
| return result; |
| } |
| |
| /* |
| * 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 + Plugin.PLUGIN_PREFERENCE_SCOPE + IPath.SEPARATOR; |
| for (Iterator i = properties.keySet().iterator(); i.hasNext();) { |
| String key = (String) i.next(); |
| String value = properties.getProperty(key); |
| 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 = new ExportedPreferences(null, EMPTY_STRING); |
| for (Iterator i = properties.keySet().iterator(); i.hasNext();) { |
| String path = (String) i.next(); |
| String value = properties.getProperty(path); |
| 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 (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Converted preferences file to IExportedPreferences tree: " + ((ExportedPreferences) result).toDeepDebugString()); //$NON-NLS-1$ |
| return result; |
| } |
| |
| /* |
| * Return the string which is the scope for the given path. |
| * Return the empty string if it cannot be determined. |
| */ |
| 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); |
| } |
| |
| /* |
| * excludesList is guarenteed not to be null |
| */ |
| private Properties convertToProperties(IEclipsePreferences preferences, final String[] excludesList) throws BackingStoreException { |
| final Properties result = new Properties(); |
| final int baseLength = preferences.absolutePath().length(); |
| |
| // create a visitor to do the export |
| IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() { |
| 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 (int i = 0; i < excludesList.length; i++) { |
| String exclusion = EclipsePreferences.makeRelative(excludesList[i]); |
| if (path.startsWith(exclusion)) |
| return false; |
| } |
| boolean needToAddVersion = InstanceScope.SCOPE.equals(scope); |
| // check the excludes list for each preference |
| String[] keys = node.keys(); |
| for (int i = 0; i < keys.length; i++) { |
| String key = keys[i]; |
| 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; |
| } |
| |
| protected IEclipsePreferences createNode(String name) { |
| IScope scope = null; |
| Object value = scopeRegistry.get(name); |
| if (value instanceof IConfigurationElement) { |
| try { |
| scope = (IScope) ((IConfigurationElement) value).createExecutableExtension(ATTRIBUTE_CLASS); |
| scopeRegistry.put(name, scope); |
| } catch (ClassCastException e) { |
| String message = Policy.bind("preferences.classCast"); //$NON-NLS-1$ |
| log(createStatusError(message, e)); |
| return new EclipsePreferences(root, name); |
| } catch (CoreException e) { |
| log(e.getStatus()); |
| return new EclipsePreferences(root, name); |
| } |
| } else |
| scope = (IScope) value; |
| return scope.create(root, name); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#exportPreferences(org.eclipse.core.runtime.preferences.IEclipsePreferences, java.io.OutputStream, java.lang.String[]) |
| */ |
| public IStatus exportPreferences(IEclipsePreferences node, OutputStream output, String[] excludesList) throws CoreException { |
| if (node == null || output == null) |
| throw new IllegalArgumentException(); |
| Properties 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) { |
| String message = Policy.bind("preferences.exportProblems"); //$NON-NLS-1$ |
| throw new CoreException(createStatusError(message, e)); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#get(java.lang.String, java.lang.String, org.osgi.service.prefs.Preferences[]) |
| */ |
| public String get(String key, String defaultValue, Preferences[] nodes) { |
| if (nodes == null) |
| return defaultValue; |
| for (int i = 0; i < nodes.length; i++) { |
| Preferences node = nodes[i]; |
| if (node != null) { |
| String result = node.get(key, null); |
| if (result != null) |
| return result; |
| } |
| } |
| return defaultValue; |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getBoolean(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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(); |
| } |
| |
| /* |
| * Return the version for the bundle with the given name. Return null if it |
| * is not known or there is a problem. |
| */ |
| String getBundleVersion(String bundleName) { |
| Bundle bundle = Platform.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; |
| } |
| |
| /* |
| * Return the name of the bundle from the given path. |
| * It is assumed that that path is: |
| * - absolute |
| * - in the instance scope |
| */ |
| 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); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getByteArray(java.lang.String, java.lang.String, byte[], org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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 : result.getBytes(); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getDefaultLookupOrder(java.lang.String, java.lang.String) |
| */ |
| public String[] getDefaultLookupOrder(String qualifier, String key) { |
| LookupOrder order = (LookupOrder) defaultsRegistry.get(getRegistryKey(qualifier, key)); |
| return order == null ? null : order.getOrder(); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getDouble(java.lang.String, java.lang.String, double, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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; |
| } |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getFloat(java.lang.String, java.lang.String, float, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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; |
| } |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getInt(java.lang.String, java.lang.String, int, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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; |
| } |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getLong(java.lang.String, java.lang.String, long, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| 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; |
| } |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getLookupOrder(java.lang.String, java.lang.String) |
| */ |
| public String[] getLookupOrder(String qualifier, String key) { |
| String[] order = getDefaultLookupOrder(qualifier, key); |
| // if there wasn't an exact match based on both qualifier and simple name |
| // then do a lookup based only on the qualifier |
| if (order == null && key != null) |
| order = getDefaultLookupOrder(qualifier, null); |
| if (order == null) |
| order = DEFAULT_DEFAULT_LOOKUP_ORDER; |
| return order; |
| } |
| |
| private Preferences[] getNodes(String qualifier, String key, IScopeContext[] contexts) { |
| String[] order = getLookupOrder(qualifier, key); |
| String childPath = EclipsePreferences.makeRelative(EclipsePreferences.decodePath(key)[0]); |
| ArrayList result = new ArrayList(); |
| for (int i = 0; i < order.length; i++) { |
| String scopeString = order[i]; |
| boolean found = false; |
| for (int j = 0; contexts != null && j < contexts.length; j++) { |
| IScopeContext 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; |
| } |
| return (Preferences[]) result.toArray(new Preferences[result.size()]); |
| } |
| |
| /* |
| * Convert the given qualifier and key into a key to use in the look-up registry. |
| */ |
| private String getRegistryKey(String qualifier, String key) { |
| if (qualifier == null) |
| throw new IllegalArgumentException(); |
| if (key == null) |
| return qualifier; |
| return qualifier + '/' + key; |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getRootNode() |
| */ |
| |
| public IEclipsePreferences getRootNode() { |
| return root; |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#getString(java.lang.String, java.lang.String, java.lang.String, org.eclipse.core.runtime.preferences.IScope[]) |
| */ |
| public String getString(String qualifier, String key, String defaultValue, IScopeContext[] scopes) { |
| return get(EclipsePreferences.decodePath(key)[1], defaultValue, getNodes(qualifier, key, scopes)); |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#importPreferences(java.io.InputStream) |
| */ |
| public IStatus importPreferences(InputStream input) throws CoreException { |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Importing preferences..."); //$NON-NLS-1$ |
| return applyPreferences(readPreferences(input)); |
| } |
| |
| /* |
| * Returns a boolean value indicating whether or not the given Properties |
| * object is the result of a preference export previous to Eclipse 3.0. |
| * |
| * Check the contents of the file. In Eclipse 3.0 we printed out a file |
| * version key. |
| */ |
| private boolean isLegacy(Properties properties) { |
| return properties.getProperty(VERSION_KEY) == null; |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#readPreferences(java.io.InputStream) |
| */ |
| public IExportedPreferences readPreferences(InputStream input) throws CoreException { |
| if (input == null) |
| throw new IllegalArgumentException(); |
| |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Reading preferences from stream..."); //$NON-NLS-1$ |
| |
| // read the file into a properties object |
| Properties properties = new Properties(); |
| try { |
| properties.load(input); |
| } catch (IOException e) { |
| String message = Policy.bind("preferences.importProblems"); //$NON-NLS-1$ |
| throw new CoreException(createStatusError(message, e)); |
| } finally { |
| try { |
| input.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| |
| // manipulate the file if it from a legacy preference export |
| if (isLegacy(properties)) { |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Read legacy preferences file, converting to 3.0 format..."); //$NON-NLS-1$ |
| properties = convertFromLegacy(properties); |
| } else { |
| if (InternalPlatform.DEBUG_PREFERENCES) |
| Policy.debug("Read preferences file."); //$NON-NLS-1$ |
| properties.remove(VERSION_KEY); |
| } |
| |
| // convert the Properties object into an object to return |
| return convertFromProperties(properties); |
| } |
| |
| public void registryChanged(IRegistryChangeEvent event) { |
| IExtensionDelta[] deltas = event.getExtensionDeltas(Platform.PI_RUNTIME, Platform.PT_PREFERENCES); |
| for (int i = 0; i < deltas.length; i++) { |
| IConfigurationElement[] elements = deltas[i].getExtension().getConfigurationElements(); |
| for (int j = 0; j < elements.length; j++) { |
| switch (deltas[i].getKind()) { |
| case IExtensionDelta.ADDED : |
| scopeAdded(elements[j]); |
| break; |
| case IExtensionDelta.REMOVED : |
| String scope = elements[j].getAttribute(ATTRIBUTE_NAME); |
| if (scope != null) |
| scopeRemoved(scope); |
| break; |
| } |
| } |
| } |
| } |
| |
| /* |
| * @see org.eclipse.core.runtime.preferences.IPreferencesService#setDefaultLookupOrder(java.lang.String, java.lang.String, java.lang.String[]) |
| */ |
| 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(qualifier, key, order); |
| defaultsRegistry.put(registryKey, obj); |
| } |
| } |
| |
| public IStatus validateVersions(IPath path) { |
| String message = Policy.bind("preferences.validate"); //$NON-NLS-1$ |
| final MultiStatus result = new MultiStatus(Platform.PI_RUNTIME, IStatus.INFO, message, null); |
| IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() { |
| public boolean visit(IEclipsePreferences node) { |
| if (!(node instanceof ExportedPreferences)) |
| return false; |
| |
| // calculate the version in the file |
| ExportedPreferences realNode = (ExportedPreferences) node; |
| String version = realNode.getVersion(); |
| if (version == null || !PluginVersionIdentifier.validateVersion(version).isOK()) |
| return true; |
| PluginVersionIdentifier versionInFile = new PluginVersionIdentifier(version); |
| |
| // calculate the version of the installed bundle |
| 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); |
| |
| // verify the versions based on the matching rules |
| 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) { |
| // ignore...if the file does not exist then all is OK |
| } catch (CoreException e) { |
| message = Policy.bind("preferences.validationException"); //$NON-NLS-1$ |
| result.add(createStatusError(message, e)); |
| } catch (BackingStoreException e) { |
| message = Policy.bind("preferences.validationException"); //$NON-NLS-1$ |
| result.add(createStatusError(message, e)); |
| } |
| return result; |
| } |
| |
| /** |
| * Compares two plugin version identifiers to see if their preferences |
| * are compatible. If they are not compatible, a warning message is |
| * added to the given multistatus, according to the following rules: |
| * |
| * - plugins that differ in service number: no status |
| * - plugins that differ in minor version: WARNING status |
| * - plugins that differ in major version: |
| * - where installed plugin is newer: WARNING status |
| * - where installed plugin is older: ERROR status |
| * @param bundle the name of the bundle |
| * @param pref The version identifer of the preferences to be loaded |
| * @param installed The version identifier of the installed plugin |
| */ |
| 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 = Policy.bind("preferences.incompatible", new String[] {pref.toString(), bundle, installed.toString()}); //$NON-NLS-1$ |
| return new Status(severity, Platform.PI_RUNTIME, 1, msg, null); |
| } |
| } |