blob: 4e8d95afff2c9c9020009040f456d4d07e7ad7b5 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2002 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.core.internal.runtime;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.*;
/**
* Utility class for exporting and importing the complete set of user-defined
* preferences for all plugins in the platform. The global preference file
* is written in the following format:
*
* <plugin-id1>=<plugin-version1>
* <plugin-id1>/<property-key1>=<property-value1>
* <plugin-id1>/<property-key2>=<property-value2>
* ...
* <plugin-id2>=<plugin-version2>
* <plugin-id2>/<property-key1>=<property-value1>
* <plugin-id2>/<property-key2>=<property-value2>
* ...
*/
public class PreferenceExporter {
/**
* The character that separates the plug-in id from the property key.
*/
private static final char PLUGIN_SEPARATOR = '/';
/**
* @see Preferences#exportPreferences
*/
public static void exportPreferences(IPath file) {
//collect all plugin preferences into a single global preference object
Preferences globalPreferences = new Preferences();
IPluginDescriptor[] descriptors = Platform.getPluginRegistry().getPluginDescriptors();
for (int i = 0; i < descriptors.length; i++) {
IPluginDescriptor descriptor = descriptors[i];
//save current preferences to ensure most recent values are exported
if (descriptor.isPluginActivated()) {
try {
descriptor.getPlugin().savePluginPreferences();
} catch (CoreException e) {
e.printStackTrace();
continue;
}
}
//now merge the plugin preferences into the global preference object
if (mergePluginPreferences(descriptor, globalPreferences)) {
//write the property that indicates the plugin version
globalPreferences.setValue(descriptor.getUniqueIdentifier(), descriptor.getVersionIdentifier().toString());
}
}
storePreferences(file, globalPreferences);
}
/**
* Returns the plugin preference file for the given plugin descriptor.
*/
private static IPath getPluginPreferenceFile(IPluginDescriptor descriptor) {
IPath location = InternalPlatform.getMetaArea().getPluginStateLocation(descriptor);
return location.append(Plugin.PREFERENCES_FILE_NAME);
}
/**
* @see Preferences#importPreferences
*/
public static void importPreferences(IPath file) {
Map idsToPreferences = splitPreferences(file);
IPluginDescriptor[] descriptors = Platform.getPluginRegistry().getPluginDescriptors();
for (int i = 0; i < descriptors.length; i++) {
setPluginPreferences(descriptors[i],
(Preferences) idsToPreferences.get(descriptors[i].getUniqueIdentifier()));
}
}
/**
* Loads preferences from the given file into the provided preferences instance.
* Returns the preferences instance.
*/
private static Preferences loadPreferences(IPath properties, Preferences preferences) {
File propertiesFile = properties.toFile();
if (propertiesFile.exists()) {
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(propertiesFile));
preferences.load(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return preferences;
}
/**
* Adds all preferences for the given plugin descriptor to the provided
* preferences instance. Returns true if any properties were added,
* and false otherwise.
*/
private static boolean mergePluginPreferences(IPluginDescriptor descriptor, Preferences preferences) {
boolean found = false;
IPath propertiesFile = getPluginPreferenceFile(descriptor);
if (propertiesFile.toFile().exists()) {
Preferences pluginPreferences = loadPreferences(propertiesFile, new Preferences());
String pluginId = descriptor.getUniqueIdentifier();
String[] keys = pluginPreferences.propertyNames();
found = keys.length > 0;
for (int i = 0; i < keys.length; i++) {
String longKey = pluginId + PLUGIN_SEPARATOR + keys[i];
preferences.setValue(longKey, pluginPreferences.getString(keys[i]));
}
}
return found;
}
/**
* Sets the given preferences as the preferences for the plugin with the
* given descriptor, overwriting any previously defined preferences. If
* the given preferences is null, all values are returned to their default value.
*/
private static void setPluginPreferences(IPluginDescriptor descriptor, Preferences newPreferences) {
if (descriptor.isPluginActivated()) {
Plugin plugin = null;
try {
plugin = descriptor.getPlugin();
} catch (CoreException e) {
e.printStackTrace();
}
if (plugin != null) {
Preferences oldPreferences = plugin.getPluginPreferences();
//remove all old values
String[] keys = oldPreferences.propertyNames();
for (int i = 0; i < keys.length; i++) {
oldPreferences.setToDefault(keys[i]);
}
//add new values
if (newPreferences != null) {
keys = newPreferences.propertyNames();
for (int i = 0; i < keys.length; i++) {
oldPreferences.setValue(keys[i], newPreferences.getString(keys[i]));
}
}
//save the preferences file
storePreferences(getPluginPreferenceFile(descriptor), oldPreferences);
}
} else {
//if the plugin isn't loaded, just save the preferences file directly
storePreferences(getPluginPreferenceFile(descriptor), newPreferences);
}
}
/**
* Splits up a global preference file into preferences for each plugin
* descriptor. Returns a map of plugin IDs to Preferences objects
* for that plugin.
*/
private static Map splitPreferences(IPath file) {
Preferences globalPreferences = loadPreferences(file, new Preferences());
Map idsToPreferences = new HashMap();
String[] keys = globalPreferences.propertyNames();
for (int i = 0; i < keys.length; i++) {
String longKey = keys[i];
int index = longKey.indexOf(PLUGIN_SEPARATOR);
if (index >= 0) {
String pluginId = longKey.substring(0, index);
String key = longKey.substring(index + 1);
Preferences preferences = (Preferences) idsToPreferences.get(pluginId);
if (preferences == null) {
preferences = new Preferences();
idsToPreferences.put(pluginId, preferences);
}
preferences.setValue(key, globalPreferences.getString(longKey));
}
}
return idsToPreferences;
}
/**
* Writes the given preferences to the given file. If the preferences are
* null or empty, the file is deleted.
*/
private static void storePreferences(IPath destination, Preferences preferences) {
File destinationFile = destination.toFile();
if (preferences == null || preferences.propertyNames().length == 0) {
destinationFile.delete();
return;
}
File parent = destinationFile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(destinationFile));
preferences.store(out, null);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 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 pref The version identifer of the preferences to be loaded
* @param installed The version identifier of the installed plugin
*/
private static void validatePluginVersions(
String pluginId,
PluginVersionIdentifier pref,
PluginVersionIdentifier installed,
MultiStatus result) {
if (installed.getMajorComponent() == pref.getMajorComponent() &&
installed.getMinorComponent() == pref.getMinorComponent()) {
return;
}
int severity;
if (installed.getMajorComponent() < pref.getMajorComponent()) {
severity = IStatus.ERROR;
} else {
severity = IStatus.WARNING;
}
String msg = Policy.bind("preferences.incompatible", new String[] { //$NON-NLS-1$
pref.toString(), pluginId, installed.toString()});
result.add(new Status(severity, Platform.PI_RUNTIME, 1, msg, null));
}
/**
* Validates that the preference versions in the given file match
* the currently installed plugins. Returns an OK status if
* all preferences match the currently installed plugins, otherwise a MultiStatus
* describing what preferences don't match.
*/
public static IStatus validatePreferenceVersions(IPath file) {
String msg = Policy.bind("preferences.validate"); //$NON-NLS-1$
MultiStatus result = new MultiStatus(Platform.PI_RUNTIME, 1, msg, null);
Preferences globalPreferences = loadPreferences(file, new Preferences());
IPluginRegistry registry = Platform.getPluginRegistry();
String[] keys = globalPreferences.propertyNames();
for (int i = 0; i < keys.length; i++) {
String pluginId = keys[i];
//if the key does not contain the separator character, it is a plugin version property
if (pluginId.indexOf(PLUGIN_SEPARATOR) < 0) {
IPluginDescriptor descriptor = registry.getPluginDescriptor(pluginId);
if (descriptor != null) {
String version = globalPreferences.getString(pluginId);
PluginVersionIdentifier preferenceVersion = new PluginVersionIdentifier(version);
PluginVersionIdentifier installedVersion = descriptor.getVersionIdentifier();
validatePluginVersions(pluginId, preferenceVersion, installedVersion, result);
}
}
}
return result;
}
}