| /* |
| * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.oomph.preferences.util; |
| |
| import org.eclipse.oomph.preferences.PreferenceNode; |
| import org.eclipse.oomph.preferences.PreferencesFactory; |
| import org.eclipse.oomph.preferences.Property; |
| import org.eclipse.oomph.util.IORuntimeException; |
| import org.eclipse.oomph.util.IOUtil; |
| import org.eclipse.oomph.util.ObjectUtil; |
| |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.impl.DESCipherImpl; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.xml.type.XMLTypeFactory; |
| |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; |
| import org.eclipse.core.runtime.preferences.IPreferenceNodeVisitor; |
| import org.eclipse.equinox.security.storage.ISecurePreferences; |
| import org.eclipse.equinox.security.storage.SecurePreferencesFactory; |
| import org.eclipse.equinox.security.storage.StorageException; |
| import org.eclipse.equinox.security.storage.provider.IProviderHints; |
| |
| import org.osgi.service.prefs.BackingStoreException; |
| import org.osgi.service.prefs.Preferences; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.lang.reflect.Method; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedHashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.WeakHashMap; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public final class PreferencesUtil |
| { |
| private static final Cipher CIPHER = new Cipher(); |
| |
| /** |
| * A resource load option to load an instance using {@link #getRootPreferenceNode(boolean) PreferencesUtil.getRootPreferenceNode(true)}. |
| * The resource must be {@link Resource#unload() unloaded}, to avoid dangling listeners. |
| */ |
| public static final String OPTION_SYNCHRONIZED_PREFERENCES = "SYNCHRONIZED_PREFERENCES"; |
| |
| public static final String BUNDLE_DEFAULTS_NODE = "bundle_defaults"; |
| |
| public static final String PREFERENCE_SCHEME = "preference"; |
| |
| public static final URI ROOT_PREFERENCE_NODE_URI = URI.createURI(PREFERENCE_SCHEME + ":/"); |
| |
| public static final String DEFAULT_NODE = "default"; |
| |
| public static final String CONFIRGURATION_NODE = "configuration"; |
| |
| public static final String INSTANCE_NODE = "instance"; |
| |
| public static final String PROJECT_NODE = "project"; |
| |
| public static final String SECURE_NODE = "secure"; |
| |
| public static final Set<String> ALL_CHILD_NODES = Collections.unmodifiableSet(new LinkedHashSet<String>(Arrays.asList(new String[] { SECURE_NODE, |
| BUNDLE_DEFAULTS_NODE, DEFAULT_NODE, CONFIRGURATION_NODE, INSTANCE_NODE, PROJECT_NODE }))); |
| |
| private static final IEclipsePreferences ROOT = Platform.getPreferencesService().getRootNode(); |
| |
| public static ISecurePreferences getSecurePreferences() |
| { |
| Map<Object, Object> options = new HashMap<Object, Object>(); |
| options.put(IProviderHints.PROMPT_USER, Boolean.FALSE); |
| |
| try |
| { |
| return SecurePreferencesFactory.open(null, options); |
| } |
| catch (IOException ex) |
| { |
| // log(ex); |
| } |
| |
| return null; |
| } |
| |
| public static PreferenceNode getRootPreferenceNode() |
| { |
| return getRootPreferenceNode(false); |
| } |
| |
| public static PreferenceNode getRootPreferenceNode(boolean isSynchronized) |
| { |
| return getRootPreferenceNode(ALL_CHILD_NODES, isSynchronized); |
| } |
| |
| public static PreferenceNode getRootPreferenceNode(Set<String> childNodes, boolean isSynchronized) |
| { |
| ResourceSet resourceSet = new ResourceSetImpl(); |
| Resource resource = resourceSet.createResource(ROOT_PREFERENCE_NODE_URI.appendSegment("*.preferences")); |
| PreferenceNode root = PreferencesFactory.eINSTANCE.createPreferenceNode(); |
| resource.getContents().add(root); |
| |
| traverse(root, childNodes == ALL_CHILD_NODES ? null : childNodes, ROOT, isSynchronized); |
| |
| if (childNodes.size() > 1) |
| { |
| int index = 0; |
| for (String name : childNodes) |
| { |
| PreferenceNode node = root.getNode(name); |
| if (node != null) |
| { |
| root.getChildren().move(index++, node); |
| } |
| } |
| } |
| |
| if (childNodes.contains(SECURE_NODE)) |
| { |
| PreferenceNode secureRoot = PreferencesFactory.eINSTANCE.createPreferenceNode(); |
| ISecurePreferences securePreferences = getSecurePreferences(); |
| if (securePreferences != null) |
| { |
| try |
| { |
| traverse(secureRoot, null, SecurePreferenceWapper.create(securePreferences), false); |
| } |
| catch (Throwable ex) |
| { |
| // Ignore |
| } |
| } |
| |
| secureRoot.setName(SECURE_NODE); |
| root.getChildren().add(0, secureRoot); |
| } |
| |
| return root; |
| } |
| |
| /** |
| * Reconciles the preferences as specified by the preference node with the real Eclipse preferences |
| * and returns the root nodes that need to be {@link IEclipsePreferences#flush() flushed} to store the changes to the backing store. |
| */ |
| public static Collection<? extends IEclipsePreferences> reconcile(PreferenceNode preferenceNode) throws BackingStoreException |
| { |
| IEclipsePreferences preferences = getPreferences(preferenceNode); |
| if (preferences == null) |
| { |
| throw new BackingStoreException("The preference node is not backed by a real Eclipse preference" + preferenceNode); |
| } |
| |
| return reconcile(preferenceNode, preferences); |
| } |
| |
| private static Collection<? extends IEclipsePreferences> reconcile(PreferenceNode preferenceNode, IEclipsePreferences preferences) |
| throws BackingStoreException |
| { |
| boolean isModified = false; |
| Set<IEclipsePreferences> result = new LinkedHashSet<IEclipsePreferences>(); |
| Set<String> childNames = new HashSet<String>(Arrays.asList(preferences.childrenNames())); |
| for (PreferenceNode child : preferenceNode.getChildren()) |
| { |
| String name = child.getName(); |
| if (childNames.remove(name)) |
| { |
| result.addAll(reconcile(child, (IEclipsePreferences)preferences.node(name))); |
| } |
| else if (preferences == ROOT && SECURE_NODE.equals(name)) |
| { |
| result.addAll(reconcile(child, SecurePreferenceWapper.create(getSecurePreferences()))); |
| } |
| else |
| { |
| isModified = true; |
| create(child, preferences); |
| } |
| } |
| |
| for (String name : childNames) |
| { |
| isModified = true; |
| preferences.node(name).removeNode(); |
| } |
| |
| Set<String> propertyNames = new HashSet<String>(Arrays.asList(preferences.keys())); |
| for (Property property : preferenceNode.getProperties()) |
| { |
| String name = property.getName(); |
| String value = property.getSecureValue(); |
| if (propertyNames.remove(name)) |
| { |
| if (!ObjectUtil.equals(value, preferences.get(name, null))) |
| { |
| isModified = true; |
| preferences.put(name, value); |
| } |
| } |
| else |
| { |
| isModified = true; |
| if (property.isSecure() && preferences instanceof ISecurePreferences) |
| { |
| ISecurePreferences securePreferences = (ISecurePreferences)preferences; |
| try |
| { |
| securePreferences.put(name, value, true); |
| } |
| catch (StorageException ex) |
| { |
| throw new BackingStoreException(ex.getMessage(), ex); |
| } |
| } |
| else |
| { |
| preferences.put(name, value); |
| } |
| } |
| } |
| |
| for (String name : propertyNames) |
| { |
| isModified = true; |
| preferences.remove(name); |
| } |
| |
| return isModified ? Collections.singleton(preferences) : result; |
| } |
| |
| private static void create(PreferenceNode preferenceNode, IEclipsePreferences preferences) |
| { |
| IEclipsePreferences childPreferences = (IEclipsePreferences)preferences.node(preferenceNode.getName()); |
| for (PreferenceNode child : preferenceNode.getChildren()) |
| { |
| create(child, childPreferences); |
| } |
| |
| for (Property property : preferenceNode.getProperties()) |
| { |
| String value = property.getSecureValue(); |
| if (value != null) |
| { |
| String name = property.getName(); |
| if (childPreferences instanceof ISecurePreferences) |
| { |
| ISecurePreferences securePreferences = (ISecurePreferences)childPreferences; |
| try |
| { |
| securePreferences.put(name, value, property.isSecure()); |
| } |
| catch (StorageException ex) |
| { |
| throw new RuntimeException(ex); |
| } |
| } |
| else |
| { |
| childPreferences.put(name, value); |
| } |
| } |
| } |
| } |
| |
| private static IEclipsePreferences getPreferences(PreferenceNode preferenceNode) throws BackingStoreException |
| { |
| if (preferenceNode == null) |
| { |
| return ROOT; |
| } |
| |
| IEclipsePreferences parentPreferences = getPreferences(preferenceNode.getParent()); |
| if (parentPreferences != null) |
| { |
| String name = preferenceNode.getName(); |
| if (parentPreferences.nodeExists(name)) |
| { |
| return (IEclipsePreferences)parentPreferences.node(name); |
| } |
| else if (parentPreferences == ROOT && SECURE_NODE.equals(name)) |
| { |
| return SecurePreferenceWapper.create(getSecurePreferences()); |
| } |
| } |
| |
| return null; |
| } |
| |
| private static void traverse(PreferenceNode preferenceNode, Set<String> childNodes, Preferences node, boolean isSynchronized) |
| { |
| try |
| { |
| if (isSynchronized && node instanceof IEclipsePreferences) |
| { |
| preferenceNode.eAdapters().add(new PreferencesAdapter((IEclipsePreferences)node)); |
| } |
| |
| preferenceNode.setName(node.name()); |
| |
| EList<PreferenceNode> children = preferenceNode.getChildren(); |
| String[] childrenNames = node.childrenNames(); |
| Arrays.sort(childrenNames); |
| for (String name : childrenNames) |
| { |
| if (childNodes == null || childNodes.contains(name)) |
| { |
| Preferences childNode = node.node(name); |
| PreferenceNode childPreferenceNode = PreferencesFactory.eINSTANCE.createPreferenceNode(); |
| children.add(childPreferenceNode); |
| traverse(childPreferenceNode, null, childNode, isSynchronized); |
| } |
| } |
| |
| EList<Property> properties = preferenceNode.getProperties(); |
| String[] keys = node.keys(); |
| Arrays.sort(keys); |
| for (String name : keys) |
| { |
| Property property = PreferencesFactory.eINSTANCE.createProperty(); |
| property.setName(name); |
| |
| if (node instanceof ISecurePreferences) |
| { |
| ISecurePreferences securePreferences = (ISecurePreferences)node; |
| try |
| { |
| boolean encrypted = securePreferences.isEncrypted(name); |
| property.setSecure(encrypted); |
| } |
| catch (StorageException ex) |
| { |
| // Ignore. |
| } |
| } |
| |
| String value = null; |
| try |
| { |
| // This can throw runtime exceptions. |
| // We should ignore any exception that might result when fetching the value. |
| value = node.get(name, null); |
| } |
| catch (RuntimeException ex) |
| { |
| // Ignore. |
| } |
| |
| property.setValue(value == null ? "" : value); |
| |
| properties.add(property); |
| } |
| } |
| catch (BackingStoreException ex) |
| { |
| // Ignore |
| } |
| } |
| |
| public static Preferences getPreferences(PreferenceNode preferenceNode, boolean demandCreate) throws BackingStoreException |
| { |
| if (preferenceNode == null) |
| { |
| return ROOT; |
| } |
| |
| Preferences parentPreferences = getPreferences(preferenceNode.getParent(), demandCreate); |
| if (parentPreferences != null) |
| { |
| String name = preferenceNode.getName(); |
| boolean exists = false; |
| if (name != null) |
| { |
| try |
| { |
| exists = parentPreferences.nodeExists(name); |
| } |
| catch (Throwable throwable) |
| { |
| // Ignore. |
| } |
| } |
| |
| if (demandCreate || exists) |
| { |
| return parentPreferences.node(name); |
| } |
| } |
| |
| return null; |
| } |
| |
| public static IPath getLocation(Preferences preferences) |
| { |
| if (preferences == null) |
| { |
| return null; |
| } |
| |
| try |
| { |
| Method getLocationMethod = preferences.getClass().getDeclaredMethod("getLocation"); |
| getLocationMethod.setAccessible(true); |
| IPath location = (IPath)getLocationMethod.invoke(preferences); |
| return location; |
| } |
| catch (Exception ex) |
| { |
| // Ignore |
| } |
| |
| return null; |
| } |
| |
| public static String encrypt(String value) |
| { |
| return CIPHER.encrypt(value); |
| } |
| |
| public static String decrypt(String value) |
| { |
| return CIPHER.decrypt(value); |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class PreferenceProperty |
| { |
| private Preferences node; |
| |
| private String property; |
| |
| public PreferenceProperty(String preferencePropertyPath) |
| { |
| node = Platform.getPreferencesService().getRootNode(); |
| |
| String[] segments = preferencePropertyPath.split("/"); |
| StringBuilder property = null; |
| boolean startProperty = false; |
| for (int i = 0; i < segments.length - 1; i++) |
| { |
| String segment = segments[i]; |
| if (property != null) |
| { |
| if (startProperty) |
| { |
| property.append('/'); |
| } |
| else |
| { |
| startProperty = true; |
| } |
| |
| property.append(segment); |
| } |
| else if (i != 0 && segment.length() == 0) |
| { |
| property = new StringBuilder(); |
| } |
| else |
| { |
| node = node.node(segment); |
| } |
| } |
| |
| if (property == null) |
| { |
| this.property = segments[segments.length - 1]; |
| } |
| else |
| { |
| this.property = property.append('/').append(segments[segments.length - 1]).toString(); |
| } |
| } |
| |
| public Preferences getNode() |
| { |
| return node; |
| } |
| |
| public String getProperty() |
| { |
| return property; |
| } |
| |
| public void set(String value) |
| { |
| if (value == null) |
| { |
| remove(); |
| } |
| else |
| { |
| node.put(property, value); |
| } |
| } |
| |
| public String get(String defaultValue) |
| { |
| return node.get(property, defaultValue); |
| } |
| |
| public void remove() |
| { |
| node.remove(property); |
| } |
| |
| public void setInt(int value) |
| { |
| node.putInt(property, value); |
| } |
| |
| public int getInt(int defaultValue) |
| { |
| return node.getInt(property, defaultValue); |
| } |
| |
| public void setLong(long value) |
| { |
| node.putLong(property, value); |
| } |
| |
| public long getLong(long defaultValue) |
| { |
| return node.getLong(property, defaultValue); |
| } |
| |
| public void setBoolean(boolean value) |
| { |
| node.putBoolean(property, value); |
| } |
| |
| public boolean getBoolean(boolean defaultValue) |
| { |
| return node.getBoolean(property, defaultValue); |
| } |
| |
| public void setFloat(float value) |
| { |
| node.putFloat(property, value); |
| } |
| |
| public float getFloat(float defaultValue) |
| { |
| return node.getFloat(property, defaultValue); |
| } |
| |
| public void setDouble(double value) |
| { |
| node.putDouble(property, value); |
| } |
| |
| public double getDouble(double defaultValue) |
| { |
| return node.getDouble(property, defaultValue); |
| } |
| |
| public void setByteArray(byte[] value) |
| { |
| if (value == null) |
| { |
| remove(); |
| } |
| else |
| { |
| node.putByteArray(property, value); |
| } |
| } |
| |
| public byte[] getByteArray(byte[] defaultValue) |
| { |
| return node.getByteArray(property, defaultValue); |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| private static class SecurePreferenceWapper implements IEclipsePreferences, ISecurePreferences |
| { |
| private static final WeakHashMap<ISecurePreferences, SecurePreferenceWapper> WRAPPERS = new WeakHashMap<ISecurePreferences, PreferencesUtil.SecurePreferenceWapper>(); |
| |
| public static SecurePreferenceWapper create(ISecurePreferences preferences) |
| { |
| if (preferences == null) |
| { |
| return null; |
| } |
| |
| synchronized (WRAPPERS) |
| { |
| SecurePreferenceWapper securePreferenceWapper = WRAPPERS.get(preferences); |
| if (securePreferenceWapper == null) |
| { |
| securePreferenceWapper = new SecurePreferenceWapper(preferences); |
| } |
| return securePreferenceWapper; |
| } |
| } |
| |
| private final ISecurePreferences preferences; |
| |
| public void put(String key, String value, boolean encrypt) throws StorageException |
| { |
| preferences.put(key, value, encrypt); |
| } |
| |
| public void putInt(String key, int value, boolean encrypt) throws StorageException |
| { |
| preferences.putInt(key, value, encrypt); |
| } |
| |
| public void putLong(String key, long value, boolean encrypt) throws StorageException |
| { |
| preferences.putLong(key, value, encrypt); |
| } |
| |
| public void putBoolean(String key, boolean value, boolean encrypt) throws StorageException |
| { |
| preferences.putBoolean(key, value, encrypt); |
| } |
| |
| public void putFloat(String key, float value, boolean encrypt) throws StorageException |
| { |
| preferences.putFloat(key, value, encrypt); |
| } |
| |
| public void putDouble(String key, double value, boolean encrypt) throws StorageException |
| { |
| preferences.putDouble(key, value, encrypt); |
| } |
| |
| public void putByteArray(String key, byte[] value, boolean encrypt) throws StorageException |
| { |
| preferences.putByteArray(key, value, encrypt); |
| } |
| |
| public SecurePreferenceWapper(ISecurePreferences preferences) |
| { |
| this.preferences = preferences; |
| } |
| |
| public boolean isEncrypted(String key) |
| { |
| try |
| { |
| return preferences.isEncrypted(key); |
| } |
| catch (StorageException ex) |
| { |
| return true; |
| } |
| } |
| |
| protected RuntimeException create(Exception exception) |
| { |
| return new RuntimeException(exception); |
| } |
| |
| public void put(String key, String value) |
| { |
| try |
| { |
| preferences.put(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public String get(String key, String def) |
| { |
| try |
| { |
| return preferences.get(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void remove(String key) |
| { |
| preferences.remove(key); |
| } |
| |
| public void addNodeChangeListener(INodeChangeListener listener) |
| { |
| } |
| |
| public void removeNodeChangeListener(INodeChangeListener listener) |
| { |
| } |
| |
| public void clear() |
| { |
| preferences.clear(); |
| } |
| |
| public void putInt(String key, int value) |
| { |
| try |
| { |
| preferences.putInt(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void addPreferenceChangeListener(IPreferenceChangeListener listener) |
| { |
| } |
| |
| public void removePreferenceChangeListener(IPreferenceChangeListener listener) |
| { |
| } |
| |
| public int getInt(String key, int def) |
| { |
| try |
| { |
| return preferences.getInt(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void removeNode() |
| { |
| preferences.removeNode(); |
| } |
| |
| public SecurePreferenceWapper node(String path) |
| { |
| return create(preferences.node(path)); |
| } |
| |
| public void putLong(String key, long value) |
| { |
| try |
| { |
| preferences.putLong(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void accept(IPreferenceNodeVisitor visitor) throws BackingStoreException |
| { |
| if (visitor.visit(this)) |
| { |
| for (String name : childrenNames()) |
| { |
| node(name).accept(visitor); |
| } |
| } |
| } |
| |
| public long getLong(String key, long def) |
| { |
| try |
| { |
| return preferences.getLong(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void putBoolean(String key, boolean value) |
| { |
| try |
| { |
| preferences.putBoolean(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public boolean getBoolean(String key, boolean def) |
| { |
| try |
| { |
| return preferences.getBoolean(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void putFloat(String key, float value) |
| { |
| try |
| { |
| preferences.putFloat(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public float getFloat(String key, float def) |
| { |
| try |
| { |
| return preferences.getFloat(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void putDouble(String key, double value) |
| { |
| try |
| { |
| preferences.putDouble(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public double getDouble(String key, double def) |
| { |
| try |
| { |
| return preferences.getDouble(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void putByteArray(String key, byte[] value) |
| { |
| try |
| { |
| preferences.putByteArray(key, value, isEncrypted(key)); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public byte[] getByteArray(String key, byte[] def) |
| { |
| try |
| { |
| return preferences.getByteArray(key, def); |
| } |
| catch (StorageException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public String[] keys() |
| { |
| return preferences.keys(); |
| } |
| |
| public String[] childrenNames() |
| { |
| return preferences.childrenNames(); |
| } |
| |
| public SecurePreferenceWapper parent() |
| { |
| return create(preferences.parent()); |
| } |
| |
| public boolean nodeExists(String pathName) |
| { |
| return preferences.nodeExists(pathName); |
| } |
| |
| public String name() |
| { |
| return preferences.name(); |
| } |
| |
| public String absolutePath() |
| { |
| return preferences.absolutePath(); |
| } |
| |
| public void flush() |
| { |
| try |
| { |
| preferences.flush(); |
| } |
| catch (IOException ex) |
| { |
| throw create(ex); |
| } |
| } |
| |
| public void sync() throws BackingStoreException |
| { |
| flush(); |
| } |
| |
| private StringBuilder toString(ISecurePreferences preferences) |
| { |
| ISecurePreferences parent = preferences.parent(); |
| StringBuilder builder; |
| if (parent != null) |
| { |
| builder = toString(parent); |
| builder.append('/'); |
| } |
| else |
| { |
| builder = new StringBuilder(); |
| } |
| |
| String name = preferences.name(); |
| if (name == null) |
| { |
| builder.append('/'); |
| builder.append(SECURE_NODE); |
| } |
| else |
| { |
| builder.append(name); |
| } |
| |
| return builder; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return toString(preferences).toString(); |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| private static class Cipher extends DESCipherImpl |
| { |
| public Cipher() |
| { |
| super(EcoreUtil.generateUUID()); |
| } |
| |
| public String encrypt(String value) |
| { |
| if (value == null) |
| { |
| return null; |
| } |
| else if ("".equals(value)) |
| { |
| return ""; |
| } |
| |
| try |
| { |
| ByteArrayOutputStream bytes = new ByteArrayOutputStream(); |
| OutputStream out = encrypt(bytes); |
| out.write(value.getBytes()); |
| out.close(); |
| return XMLTypeFactory.eINSTANCE.convertBase64Binary(bytes.toByteArray()); |
| } |
| catch (Exception ex) |
| { |
| throw new IORuntimeException(ex); |
| } |
| } |
| |
| public String decrypt(String value) |
| { |
| if (value == null) |
| { |
| return null; |
| } |
| else if ("".equals(value)) |
| { |
| return ""; |
| } |
| |
| ByteArrayInputStream byteValue = new ByteArrayInputStream(XMLTypeFactory.eINSTANCE.createBase64Binary(value)); |
| try |
| { |
| ByteArrayOutputStream bytes = new ByteArrayOutputStream(); |
| InputStream in = decrypt(byteValue); |
| IOUtil.copy(in, bytes); |
| return new String(bytes.toByteArray()); |
| } |
| catch (Exception ex) |
| { |
| throw new IORuntimeException(ex); |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| private static class PreferencesAdapter extends AdapterImpl implements IEclipsePreferences.INodeChangeListener, IEclipsePreferences.IPreferenceChangeListener |
| { |
| protected IEclipsePreferences preferences; |
| |
| public PreferencesAdapter(IEclipsePreferences preferences) |
| { |
| this.preferences = preferences; |
| |
| preferences.addNodeChangeListener(this); |
| preferences.addPreferenceChangeListener(this); |
| } |
| |
| @Override |
| public boolean isAdapterForType(Object type) |
| { |
| return type == PreferencesAdapter.class; |
| } |
| |
| public void preferenceChange(PreferenceChangeEvent event) |
| { |
| PreferenceNode preferenceNode = (PreferenceNode)target; |
| Resource resource = preferenceNode.eResource(); |
| if (resource == null) |
| { |
| handlePreferenceChange(event, preferenceNode); |
| } |
| else |
| { |
| ResourceSet resourceSet = resource.getResourceSet(); |
| synchronized (resource) |
| { |
| synchronized (resourceSet) |
| { |
| handlePreferenceChange(event, preferenceNode); |
| } |
| } |
| } |
| } |
| |
| private void handlePreferenceChange(PreferenceChangeEvent event, PreferenceNode preferenceNode) |
| { |
| String name = event.getKey(); |
| Object value = event.getNewValue(); |
| EList<Property> properties = preferenceNode.getProperties(); |
| for (int i = 0, size = properties.size(); i < size; ++i) |
| { |
| Property property = properties.get(i); |
| int comparison = property.getName().compareTo(name); |
| if (comparison == 0) |
| { |
| if (value == null) |
| { |
| properties.remove(i); |
| } |
| else |
| { |
| property.setValue(value.toString()); |
| } |
| |
| return; |
| } |
| else if (comparison > 0) |
| { |
| if (value != null) |
| { |
| property = PreferencesFactory.eINSTANCE.createProperty(); |
| property.setName(name); |
| property.setValue(value.toString()); |
| properties.add(i, property); |
| } |
| |
| return; |
| } |
| } |
| |
| Property property = PreferencesFactory.eINSTANCE.createProperty(); |
| property.setName(name); |
| property.setValue(value.toString()); |
| properties.add(property); |
| } |
| |
| public void added(NodeChangeEvent event) |
| { |
| PreferenceNode preferenceNode = (PreferenceNode)target; |
| Resource resource = preferenceNode.eResource(); |
| if (resource == null) |
| { |
| handleAdded(event, preferenceNode); |
| } |
| else |
| { |
| synchronized (resource) |
| { |
| ResourceSet resourceSet = resource.getResourceSet(); |
| synchronized (resourceSet) |
| { |
| handleAdded(event, preferenceNode); |
| } |
| } |
| } |
| } |
| |
| private void handleAdded(NodeChangeEvent event, PreferenceNode preferenceNode) |
| { |
| Preferences childNode = event.getChild(); |
| String name = childNode.name(); |
| if (preferenceNode.getNode(name) == null) |
| { |
| PreferenceNode childPreferenceNode = PreferencesFactory.eINSTANCE.createPreferenceNode(); |
| childPreferenceNode.setName(name); |
| EList<PreferenceNode> children = preferenceNode.getChildren(); |
| int index = 0; |
| for (int size = children.size(); index < size; ++index) |
| { |
| PreferenceNode otherChildPreferenceNode = children.get(index); |
| if (otherChildPreferenceNode.getName().compareTo(name) >= 0) |
| { |
| break; |
| } |
| } |
| |
| children.add(index, childPreferenceNode); |
| traverse(childPreferenceNode, null, childNode, true); |
| } |
| } |
| |
| public void removed(NodeChangeEvent event) |
| { |
| PreferenceNode preferenceNode = (PreferenceNode)target; |
| Resource resource = preferenceNode.eResource(); |
| if (resource == null) |
| { |
| handleRemoved(event, preferenceNode); |
| } |
| else |
| { |
| ResourceSet resourceSet = resource.getResourceSet(); |
| synchronized (resource) |
| { |
| synchronized (resourceSet) |
| { |
| handleRemoved(event, preferenceNode); |
| } |
| } |
| } |
| } |
| |
| private void handleRemoved(NodeChangeEvent event, PreferenceNode preferenceNode) |
| { |
| Preferences childNode = event.getChild(); |
| String name = childNode.name(); |
| |
| EList<PreferenceNode> children = preferenceNode.getChildren(); |
| for (int i = 0, size = children.size(); i < size; ++i) |
| { |
| PreferenceNode childPreferenceNode = children.get(i); |
| if (childPreferenceNode.getName().equals(name)) |
| { |
| children.remove(i); |
| return; |
| } |
| } |
| } |
| |
| @Override |
| public void unsetTarget(Notifier oldTarget) |
| { |
| super.unsetTarget(oldTarget); |
| |
| preferences.removeNodeChangeListener(this); |
| preferences.removePreferenceChangeListener(this); |
| } |
| } |
| } |