| /******************************************************************************* |
| * Copyright (c) 2008 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.security.storage; |
| |
| import java.net.URL; |
| import java.util.HashMap; |
| import java.util.Map; |
| import org.eclipse.equinox.security.storage.ISecurePreferences; |
| import org.eclipse.equinox.security.storage.provider.IPreferencesContainer; |
| |
| /** |
| * NOTE NOTE NOTE: this Javadoc is implementation details - this is not an API |
| * but a few notes on implementation design. |
| * |
| * For a URL we get one secure preference tree that contains data. The top node |
| * of that tree has a "root" type, it has special properties - the location, status, |
| * and knowledge as to how persist the tree. |
| * |
| * On the user side - let's say we have the following preferences open via factory: |
| * |
| * UserPreferences1 (Options1, URL1) |
| * UserPreferences2 (Options2, URL1) |
| * UserPreferences3 (Options3, URL2) |
| * UserPreferences4 (Options4, URL2) |
| * |
| * When we'll have 2 actual "back end" secure preferences tree with data: |
| * |
| * [UserPreferences1] -> [Options1] + |
| * \ |
| * [secure preferences1] <- 1 : 1 -> URL1 |
| * / |
| * [UserPreferences2] -> [Options2] + |
| * |
| * [UserPreferences3] -> [Options3] + |
| * \ |
| * [secure preferences2] <- 1 : 1 -> URL2 |
| * / |
| * [UserPreferences4] -> [Options4] + |
| * |
| * The user-facing nodes are actually a (node + options for this container). User-facing |
| * nodes are called wrappers as they primarily wrap secure preferences nodes. |
| * |
| * Containers are used to combine all wrappers created for the set of options. This way |
| * users don't have to specify options on each get...() / put...() method. |
| * |
| * Additionally, containers cache wrappers so that navigation on preferences tree won't |
| * create new wrappers every time process navigates from one node on the tree to another. |
| * |
| * Password provider modules: |
| * |
| * Note that only a single instance of each password provider is ever created. However, |
| * those instances are passed options as arguments. |
| */ |
| public class SecurePreferencesContainer implements IPreferencesContainer { |
| |
| private Map wrappers = new HashMap(); // node -> SecurePreferencesWrapper |
| |
| final private Map options; |
| final private SecurePreferencesRoot root; |
| |
| public SecurePreferencesContainer(SecurePreferencesRoot root, Map options) { |
| this.root = root; |
| if (options != null) { // make a copy to avoid problems if original is modified later |
| this.options = new HashMap(options.size()); |
| this.options.putAll(options); |
| } else |
| this.options = new HashMap(2); |
| } |
| |
| public ISecurePreferences wrapper(SecurePreferences node) { |
| synchronized (wrappers) { |
| if (wrappers.containsKey(node)) |
| return (ISecurePreferences) wrappers.get(node); |
| SecurePreferencesWrapper newWrapper = new SecurePreferencesWrapper(node, this); |
| wrappers.put(node, newWrapper); |
| return newWrapper; |
| } |
| } |
| |
| public void removeWrapper(SecurePreferences node) { |
| synchronized (wrappers) { |
| if (wrappers.containsKey(node)) |
| wrappers.remove(node); |
| } |
| } |
| |
| public URL getLocation() { |
| return root.getLocation(); |
| } |
| |
| public ISecurePreferences getPreferences() { |
| return wrapper(root); |
| } |
| |
| public SecurePreferencesRoot getRootData() { |
| return root; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////////// |
| // Handling of options |
| |
| public boolean hasOption(Object key) { |
| synchronized (options) { |
| return options.containsKey(key); |
| } |
| } |
| |
| public Object getOption(Object key) { |
| synchronized (options) { |
| return options.get(key); |
| } |
| } |
| |
| public Object setOption(Object key, Object value) { |
| synchronized (options) { |
| return options.put(key, value); |
| } |
| } |
| |
| public Object removeOption(Object key) { |
| synchronized (options) { |
| return options.remove(key); |
| } |
| } |
| } |