/******************************************************************************* * Copyright (c) 2010, 2014 Tasktop Technologies 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: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.commons.repositories.core; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.runtime.Assert; import org.eclipse.mylyn.commons.repositories.core.auth.ICredentialsStore; import org.eclipse.mylyn.commons.repositories.core.auth.UnavailableException; /** * @author Steffen Pingel */ public class InMemoryCredentialsStore implements ICredentialsStore { private static class Item { boolean encrypted; boolean persisted; Object value; Class<?> type; } static Map<String, InMemoryCredentialsStore> storeById = new HashMap<String, InMemoryCredentialsStore>(); public synchronized static InMemoryCredentialsStore getStore(String id) { Assert.isNotNull(id); InMemoryCredentialsStore store = storeById.get(id); if (store == null) { store = new InMemoryCredentialsStore(id); storeById.put(id, store); } return store; } private final String id; private final ICredentialsStore parent; /** * Protected by <code>this</code>. */ private final Map<String, Item> store; /** * Flag that controls if removed values are set to null or if the key is removed. This affects the behavior of * {@link #copyTo(ICredentialsStore)}. If the flag is set to <code>true</code> removed keys will also be removed in * target store. */ private final boolean keepRemovedKeys; public InMemoryCredentialsStore() { this(null, null, true); } public InMemoryCredentialsStore(ICredentialsStore parent) { this(parent, null, true); } InMemoryCredentialsStore(ICredentialsStore parent, String id, boolean keepRemovedKeys) { this.parent = parent; this.id = id; this.keepRemovedKeys = keepRemovedKeys; this.store = new HashMap<String, Item>(); } InMemoryCredentialsStore(String id) { this(null, id, false); } public synchronized void clear() { store.clear(); } public void copyTo(ICredentialsStore target) { synchronized (target) { synchronized (this) { for (Map.Entry<String, Item> entry : store.entrySet()) { Item item = entry.getValue(); if (item != null) { if (item.type == String.class) { target.put(entry.getKey(), (String) item.value, item.encrypted, item.persisted); } else if (item.type == byte[].class) { target.putByteArray(entry.getKey(), (byte[]) item.value, item.encrypted); } else if (item.type == boolean.class) { target.putBoolean(entry.getKey(), (Boolean) item.value, item.encrypted); } } else { target.remove(entry.getKey()); } } } } } /** * Clears removed items. */ public synchronized void flush() throws IOException { for (Iterator<Map.Entry<String, Item>> it = store.entrySet().iterator(); it.hasNext();) { if (it.next().getValue() == null) { it.remove(); } } } public synchronized String get(String key, String def) { Item item = store.get(key); if (item == null && parent != null) { return parent.get(key, def); } return (item != null && item.type == String.class) ? (String) item.value : def; } public synchronized boolean getBoolean(String key, boolean def) { Item item = store.get(key); if (item == null && parent != null) { return parent.getBoolean(key, def); } return (item != null && item.type == boolean.class) ? (Boolean) item.value : def; } public synchronized byte[] getByteArray(String key, byte[] def) { Item item = store.get(key); if (item == null && parent != null) { return parent.getByteArray(key, def); } return (item != null && item.type == byte[].class) ? (byte[]) item.value : def; } public String getId() { return id; } public synchronized boolean hasKey(String key) { // store.containsKey(key) would return true for removed items that were set to null return store.get(key) != null; } public synchronized String[] keys() { List<String> keys = new ArrayList<String>(store.keySet().size()); for (Entry<String, Item> entry : store.entrySet()) { if (entry.getValue() != null) { keys.add(entry.getKey()); } } return keys.toArray(new String[0]); } public synchronized void put(String key, String value, boolean encrypt) { put(key, value, encrypt, true); } public synchronized void put(String key, String value, boolean encrypt, boolean persist) { store.put(key, createItem(String.class, value, encrypt, persist)); } public synchronized void putBoolean(String key, boolean value, boolean encrypt) { store.put(key, createItem(boolean.class, value, encrypt, true)); } public synchronized void putByteArray(String key, byte[] value, boolean encrypt) { store.put(key, createItem(byte[].class, value, encrypt, encrypt)); } public synchronized void remove(String key) { if (keepRemovedKeys) { store.put(key, null); } else { store.remove(key); } } @Override public void testAvailability() throws UnavailableException { // always available } private Item createItem(Class<?> type, Object value, boolean encrypt, boolean persist) { Item item = new Item(); item.value = value; item.encrypted = encrypt; item.persisted = persist; item.type = type; return item; } }