/* AbstractPreferences -- Partial implementation of a Preference node
   Copyright (C) 2001, 2003, 2004, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util.prefs;

import gnu.java.util.prefs.EventDispatcher;
import gnu.java.util.prefs.NodeWriter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeSet;

/**
 * Partial implementation of a Preference node.
 *
 * @since 1.4
 * @author Mark Wielaard (mark@klomp.org)
 */
public abstract class AbstractPreferences extends Preferences {

    // protected fields

    /**
     * Object used to lock this preference node. Any thread only locks nodes
     * downwards when it has the lock on the current node. No method should
     * synchronize on the lock of any of its parent nodes while holding the
     * lock on the current node.
     */
    protected final Object lock = new Object();

    /**
     * Set to true in the contructor if the node did not exist in the backing
     * store when this preference node object was created. Should be set in
     * the constructor of a subclass. Defaults to false. Used to fire node
     * changed events.
     */
    protected boolean newNode = false;

    // private fields

    /**
     * The parent preferences node or null when this is the root node.
     */
    private final AbstractPreferences parent;

    /**
     * The name of this node.
     * Only when this is a root node (parent == null) the name is empty.
     * It has a maximum of 80 characters and cannot contain any '/' characters.
     */
    private final String name;

    /** True when this node has been remove, false otherwise. */
    private boolean removed = false;

    /**
     * Holds all the child names and nodes of this node that have been
     * accessed by earlier <code>getChild()</code> or <code>childSpi()</code>
     * invocations and that have not been removed.
     */
    private HashMap<String, AbstractPreferences> childCache
      = new HashMap<String, AbstractPreferences>();

    /**
     * A list of all the registered NodeChangeListener objects.
     */
    private ArrayList<NodeChangeListener> nodeListeners;

    /**
     * A list of all the registered PreferenceChangeListener objects.
     */
    private ArrayList<PreferenceChangeListener> preferenceListeners;

    // constructor

    /**
     * Creates a new AbstractPreferences node with the given parent and name.
     * 
     * @param parent the parent of this node or null when this is the root node
     * @param name the name of this node, can not be null, only 80 characters
     *             maximum, must be empty when parent is null and cannot
     *             contain any '/' characters
     * @exception IllegalArgumentException when name is null, greater then 80
     *            characters, not the empty string but parent is null or
     *            contains a '/' character
     */
    protected AbstractPreferences(AbstractPreferences parent, String name) {
        if (  (name == null)                            // name should be given
           || (name.length() > MAX_NAME_LENGTH)         // 80 characters max
           || (parent == null && name.length() != 0)    // root has no name
           || (parent != null && name.length() == 0)    // all other nodes do
           || (name.indexOf('/') != -1))                // must not contain '/'
            throw new IllegalArgumentException("Illegal name argument '"
                                               + name
                                               + "' (parent is "
                                               + (parent == null ? "" : "not ")
                                               + "null)");
        this.parent = parent;
        this.name = name;
    }

    // identification methods

    /**
     * Returns the absolute path name of this preference node.
     * The absolute path name of a node is the path name of its parent node
     * plus a '/' plus its own name. If the node is the root node and has no
     * parent then its path name is "" and its absolute path name is "/".
     */
    public String absolutePath() {
        if (parent == null)
            return "/";
        else
            return parent.path() + '/' + name;
    }

    /**
     * Private helper method for absolutePath. Returns the empty string for a
     * root node and otherwise the parentPath of its parent plus a '/'.
     */
    private String path() {
        if (parent == null)
            return "";
        else
            return parent.path() + '/' + name;
    }

    /**
     * Returns true if this node comes from the user preferences tree, false
     * if it comes from the system preferences tree.
     */
    public boolean isUserNode() {
        AbstractPreferences root = this;
	while (root.parent != null)
	    root = root.parent;
	return root == Preferences.userRoot();
    }

    /**
     * Returns the name of this preferences node. The name of the node cannot
     * be null, can be mostly 80 characters and cannot contain any '/'
     * characters. The root node has as name "".
     */
    public String name() {
        return name;
    }

    /**
     * Returns the String given by
     * <code>
     * (isUserNode() ? "User":"System") + " Preference Node: " + absolutePath()
     * </code>
     */
    public String toString() {
        return (isUserNode() ? "User":"System")
               + " Preference Node: "
               + absolutePath();
    }

    /**
     * Returns all known unremoved children of this node.
     *
     * @return All known unremoved children of this node
     */
    protected final AbstractPreferences[] cachedChildren()
    {
      Collection<AbstractPreferences> vals = childCache.values();
      return vals.toArray(new AbstractPreferences[vals.size()]);
    }

    /**
     * Returns all the direct sub nodes of this preferences node.
     * Needs access to the backing store to give a meaningfull answer.
     * <p>
     * This implementation locks this node, checks if the node has not yet
     * been removed and throws an <code>IllegalStateException</code> when it
     * has been. Then it creates a new <code>TreeSet</code> and adds any
     * already cached child nodes names. To get any uncached names it calls
     * <code>childrenNamesSpi()</code> and adds the result to the set. Finally
     * it calls <code>toArray()</code> on the created set. When the call to
     * <code>childrenNamesSpi</code> thows an <code>BackingStoreException</code>
     * this method will not catch that exception but propagate the exception
     * to the caller.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException when this node has been removed
     */
    public String[] childrenNames() throws BackingStoreException {
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            TreeSet<String> childrenNames = new TreeSet<String>();

            // First get all cached node names
            childrenNames.addAll(childCache.keySet());
            
            // Then add any others
            String names[] = childrenNamesSpi();
            for (int i = 0; i < names.length; i++) {
                childrenNames.add(names[i]);
            }

            // And return the array of names
            String[] children = new String[childrenNames.size()];
            childrenNames.toArray(children);
            return children;

        }
    }

    /**
     * Returns a sub node of this preferences node if the given path is
     * relative (does not start with a '/') or a sub node of the root
     * if the path is absolute (does start with a '/').
     * <p>
     * This method first locks this node and checks if the node has not been
     * removed, if it has been removed it throws an exception. Then if the
     * path is relative (does not start with a '/') it checks if the path is
     * legal (does not end with a '/' and has no consecutive '/' characters).
     * Then it recursively gets a name from the path, gets the child node
     * from the child-cache of this node or calls the <code>childSpi()</code>
     * method to create a new child sub node. This is done recursively on the
     * newly created sub node with the rest of the path till the path is empty.
     * If the path is absolute (starts with a '/') the lock on this node is
     * droped and this method is called on the root of the preferences tree
     * with as argument the complete path minus the first '/'.
     *
     * @exception IllegalStateException if this node has been removed
     * @exception IllegalArgumentException if the path contains two or more
     * consecutive '/' characters, ends with a '/' charactor and is not the
     * string "/" (indicating the root node) or any name on the path is more
     * than 80 characters long
     */
    public Preferences node(String path) {
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            // Is it a relative path?
            if (!path.startsWith("/")) {

                // Check if it is a valid path
                if (path.indexOf("//") != -1 || path.endsWith("/"))
                    throw new IllegalArgumentException(path);

                return getNode(path);
            }
        }

        // path started with a '/' so it is absolute
        // we drop the lock and start from the root (omitting the first '/')
        Preferences root = isUserNode() ? userRoot() : systemRoot();
        return root.node(path.substring(1));

    }

    /**
     * Private helper method for <code>node()</code>. Called with this node
     * locked. Returns this node when path is the empty string, if it is not
     * empty the next node name is taken from the path (all chars till the
     * next '/' or end of path string) and the node is either taken from the
     * child-cache of this node or the <code>childSpi()</code> method is called
     * on this node with the name as argument. Then this method is called
     * recursively on the just constructed child node with the rest of the
     * path.
     *
     * @param path should not end with a '/' character and should not contain
     *        consecutive '/' characters
     * @exception IllegalArgumentException if path begins with a name that is
     *            larger then 80 characters.
     */
    private Preferences getNode(String path) {
        // if mark is dom then goto end

        // Empty String "" indicates this node
        if (path.length() == 0)
            return this;

        // Calculate child name and rest of path
        String childName;
        String childPath;
        int nextSlash = path.indexOf('/');
        if (nextSlash == -1) {
            childName = path;
            childPath = "";
        } else {
            childName = path.substring(0, nextSlash);
            childPath = path.substring(nextSlash+1);
        }

        // Get the child node
        AbstractPreferences child;
        child = (AbstractPreferences)childCache.get(childName);
        if (child == null) {

            if (childName.length() > MAX_NAME_LENGTH)
               throw new IllegalArgumentException(childName); 

            // Not in childCache yet so create a new sub node
            child = childSpi(childName);
            childCache.put(childName, child);
            if (child.newNode && nodeListeners != null)
              fire(new NodeChangeEvent(this, child), true);
        }

        // Lock the child and go down
        synchronized(child.lock) {
            return child.getNode(childPath);
        }
    }

    /**
     * Returns true if the node that the path points to exists in memory or
     * in the backing store. Otherwise it returns false or an exception is
     * thrown. When this node is removed the only valid parameter is the
     * empty string (indicating this node), the return value in that case
     * will be false.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     *            and the path is not the empty string (indicating this node)
     * @exception IllegalArgumentException if the path contains two or more
     * consecutive '/' characters, ends with a '/' charactor and is not the
     * string "/" (indicating the root node) or any name on the path is more
     * then 80 characters long
     */
    public boolean nodeExists(String path) throws BackingStoreException {
        synchronized(lock) {
            if (isRemoved() && path.length() != 0)
                throw new IllegalStateException("Node removed");

            // Is it a relative path?
            if (!path.startsWith("/")) {

                // Check if it is a valid path
                if (path.indexOf("//") != -1 || path.endsWith("/"))
                    throw new IllegalArgumentException(path);

                return existsNode(path);
            }
        }

        // path started with a '/' so it is absolute
        // we drop the lock and start from the root (omitting the first '/')
        Preferences root = isUserNode() ? userRoot() : systemRoot();
        return root.nodeExists(path.substring(1));

    }

    private boolean existsNode(String path) throws BackingStoreException {

        // Empty String "" indicates this node
        if (path.length() == 0)
            return(!isRemoved());

        // Calculate child name and rest of path
        String childName;
        String childPath;
        int nextSlash = path.indexOf('/');
        if (nextSlash == -1) {
            childName = path;
            childPath = "";
        } else {
            childName = path.substring(0, nextSlash);
            childPath = path.substring(nextSlash+1);
        }

        // Get the child node
        AbstractPreferences child;
        child = (AbstractPreferences)childCache.get(childName);
        if (child == null) {

            if (childName.length() > MAX_NAME_LENGTH)
               throw new IllegalArgumentException(childName);

            // Not in childCache yet so create a new sub node
            child = getChild(childName);

            if (child == null)
                return false;

            childCache.put(childName, child);
        }

        // Lock the child and go down
        synchronized(child.lock) {
            return child.existsNode(childPath);
        }
    }

    /**
     * Returns the child sub node if it exists in the backing store or null
     * if it does not exist. Called (indirectly) by <code>nodeExists()</code>
     * when a child node name can not be found in the cache.
     * <p>
     * Gets the lock on this node, calls <code>childrenNamesSpi()</code> to
     * get an array of all (possibly uncached) children and compares the
     * given name with the names in the array. If the name is found in the
     * array <code>childSpi()</code> is called to get an instance, otherwise
     * null is returned.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     */
    protected AbstractPreferences getChild(String name)
                                    throws BackingStoreException
    {
        synchronized(lock) {
            // Get all the names (not yet in the cache)
            String[] names = childrenNamesSpi();
            for (int i=0; i < names.length; i++)
                if (name.equals(names[i]))
                    return childSpi(name);
           
            // No child with that name found
            return null;
        }
    }

    /**
     * Returns true if this node has been removed with the
     * <code>removeNode()</code> method, false otherwise.
     * <p>
     * Gets the lock on this node and then returns a boolean field set by
     * <code>removeNode</code> methods.
     */
    protected boolean isRemoved() {
        synchronized(lock) {
            return removed;
        }
    }

    /**
     * Returns the parent preferences node of this node or null if this is
     * the root of the preferences tree.
     * <p>
     * Gets the lock on this node, checks that the node has not been removed
     * and returns the parent given to the constructor.
     *
     * @exception IllegalStateException if this node has been removed
     */
    public Preferences parent() {
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            return parent;
        }
    }

    // export methods

    // Inherit javadoc.
    public void exportNode(OutputStream os)
                                    throws BackingStoreException,
                                           IOException
    {
        NodeWriter nodeWriter = new NodeWriter(this, os);
        nodeWriter.writePrefs();
    }

    // Inherit javadoc.
    public void exportSubtree(OutputStream os)
                                    throws BackingStoreException,
                                           IOException
    {
        NodeWriter nodeWriter = new NodeWriter(this, os);
        nodeWriter.writePrefsTree();
    }

    // preference entry manipulation methods

    /**
     * Returns an (possibly empty) array with all the keys of the preference
     * entries of this node.
     * <p>
     * This method locks this node and checks if the node has not been
     * removed, if it has been removed it throws an exception, then it returns
     * the result of calling <code>keysSpi()</code>.
     * 
     * @exception BackingStoreException when the backing store cannot be     
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public String[] keys() throws BackingStoreException {
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            return keysSpi();
        }
    }


    /**
     * Returns the value associated with the key in this preferences node. If
     * the default value of the key cannot be found in the preferences node
     * entries or something goes wrong with the backing store the supplied
     * default value is returned.
     * <p>
     * Checks that key is not null and not larger then 80 characters,
     * locks this node, and checks that the node has not been removed.
     * Then it calls <code>keySpi()</code> and returns
     * the result of that method or the given default value if it returned
     * null or throwed an exception.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public String get(String key, String defaultVal) {
        if (key.length() > MAX_KEY_LENGTH)
            throw new IllegalArgumentException(key);

        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            String value;
            try {
                value = getSpi(key);
            } catch (ThreadDeath death) {
                throw death;
            } catch (Throwable t) {
                value = null;
            }

            if (value != null) {
                return value;
            } else {
                return defaultVal;
            }
        }
    }

    /**
     * Convenience method for getting the given entry as a boolean.
     * When the string representation of the requested entry is either
     * "true" or "false" (ignoring case) then that value is returned,
     * otherwise the given default boolean value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public boolean getBoolean(String key, boolean defaultVal) {
        String value = get(key, null);

        if ("true".equalsIgnoreCase(value))
            return true;

        if ("false".equalsIgnoreCase(value))
            return false;
        
        return defaultVal;
    }

    /**
     * Convenience method for getting the given entry as a byte array.
     * When the string representation of the requested entry is a valid
     * Base64 encoded string (without any other characters, such as newlines)
     * then the decoded Base64 string is returned as byte array,
     * otherwise the given default byte array value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public byte[] getByteArray(String key, byte[] defaultVal) {
        String value = get(key, null);

        byte[] b = null;
        if (value != null) {
            b = decode64(value);
        }

        if (b != null)
            return b;
        else
            return defaultVal;
    }
    
    /**
     * Helper method for decoding a Base64 string as an byte array.
     * Returns null on encoding error. This method does not allow any other
     * characters present in the string then the 65 special base64 chars.
     */
    private static byte[] decode64(String s) {
        ByteArrayOutputStream bs = new ByteArrayOutputStream((s.length()/4)*3);
        char[] c = new char[s.length()];
        s.getChars(0, s.length(), c, 0);

        // Convert from base64 chars
        int endchar = -1;
        for(int j = 0; j < c.length && endchar == -1; j++) {
            if (c[j] >= 'A' && c[j] <= 'Z') {
                c[j] -= 'A';
            } else if (c[j] >= 'a' && c[j] <= 'z') {
                c[j] = (char) (c[j] + 26 - 'a');
            } else if (c[j] >= '0' && c[j] <= '9') {
                c[j] = (char) (c[j] + 52 - '0');
            } else if (c[j] == '+') {
                c[j] = 62;
            } else if (c[j] == '/') {
                c[j] = 63;
            } else if (c[j] == '=') {
                endchar = j;
            } else {
                return null; // encoding exception
            }
        }

        int remaining = endchar == -1 ? c.length : endchar;
        int i = 0;
        while (remaining > 0) {
            // Four input chars (6 bits) are decoded as three bytes as
            // 000000 001111 111122 222222

            byte b0 = (byte) (c[i] << 2);
            if (remaining >= 2) {
                b0 += (c[i+1] & 0x30) >> 4;
            }
            bs.write(b0);

            if (remaining >= 3) {
                byte b1 = (byte) ((c[i+1] & 0x0F) << 4);
                b1 += (byte) ((c[i+2] & 0x3C) >> 2);
                bs.write(b1);
            }

            if (remaining >= 4) {
                byte b2 = (byte) ((c[i+2] & 0x03) << 6);
                b2 += c[i+3];
                bs.write(b2);
            }

            i += 4;
            remaining -= 4;
        }

        return bs.toByteArray();
    }

    /**
     * Convenience method for getting the given entry as a double.
     * When the string representation of the requested entry can be decoded
     * with <code>Double.parseDouble()</code> then that double is returned,
     * otherwise the given default double value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public double getDouble(String key, double defaultVal) {
        String value = get(key, null);

        if (value != null) {
            try {
                return Double.parseDouble(value);
            } catch (NumberFormatException nfe) { /* ignore */ }
        }

        return defaultVal;
    }

    /**
     * Convenience method for getting the given entry as a float.
     * When the string representation of the requested entry can be decoded
     * with <code>Float.parseFloat()</code> then that float is returned,
     * otherwise the given default float value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public float getFloat(String key, float defaultVal) {
        String value = get(key, null);

        if (value != null) {
            try {
                return Float.parseFloat(value);
            } catch (NumberFormatException nfe) { /* ignore */ }
        }

        return defaultVal;
    }

    /**
     * Convenience method for getting the given entry as an integer.
     * When the string representation of the requested entry can be decoded
     * with <code>Integer.parseInt()</code> then that integer is returned,
     * otherwise the given default integer value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public int getInt(String key, int defaultVal) {
        String value = get(key, null);

        if (value != null) {
            try {
                return Integer.parseInt(value);
            } catch (NumberFormatException nfe) { /* ignore */ }
        }

        return defaultVal;
    }

    /**
     * Convenience method for getting the given entry as a long.
     * When the string representation of the requested entry can be decoded
     * with <code>Long.parseLong()</code> then that long is returned,
     * otherwise the given default long value is returned.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public long getLong(String key, long defaultVal) {
        String value = get(key, null);

        if (value != null) {
            try {
                return Long.parseLong(value);
            } catch (NumberFormatException nfe) { /* ignore */ }
        }

        return defaultVal;
    }

    /**
     * Sets the value of the given preferences entry for this node.
     * Key and value cannot be null, the key cannot exceed 80 characters
     * and the value cannot exceed 8192 characters.
     * <p>
     * The result will be immediately visible in this VM, but may not be
     * immediately written to the backing store.
     * <p>
     * Checks that key and value are valid, locks this node, and checks that
     * the node has not been removed. Then it calls <code>putSpi()</code>.
     *
     * @exception NullPointerException if either key or value are null
     * @exception IllegalArgumentException if either key or value are to large
     * @exception IllegalStateException when this node has been removed
     */
    public void put(String key, String value) {
        if (key.length() > MAX_KEY_LENGTH
            || value.length() > MAX_VALUE_LENGTH)
            throw new IllegalArgumentException("key ("
                                               + key.length() + ")"
                                               + " or value ("
                                               + value.length() + ")"
                                               + " to large");
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            putSpi(key, value);

            if (preferenceListeners != null)
              fire(new PreferenceChangeEvent(this, key, value));
        }
            
    }

    /**
     * Convenience method for setting the given entry as a boolean.
     * The boolean is converted with <code>Boolean.toString(value)</code>
     * and then stored in the preference entry as that string.
     *
     * @exception NullPointerException if key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putBoolean(String key, boolean value) {
        put(key, Boolean.toString(value));
    }

    /**
     * Convenience method for setting the given entry as an array of bytes.
     * The byte array is converted to a Base64 encoded string
     * and then stored in the preference entry as that string.
     * <p>
     * Note that a byte array encoded as a Base64 string will be about 1.3
     * times larger then the original length of the byte array, which means
     * that the byte array may not be larger about 6 KB.
     *
     * @exception NullPointerException if either key or value are null
     * @exception IllegalArgumentException if either key or value are to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putByteArray(String key, byte[] value) {
        put(key, encode64(value));
    }

    /**
     * Helper method for encoding an array of bytes as a Base64 String.
     */
    private static String encode64(byte[] b) {
        StringBuffer sb = new StringBuffer((b.length/3)*4);

        int i = 0;
        int remaining = b.length;
        char c[] = new char[4];
        while (remaining > 0) {
            // Three input bytes are encoded as four chars (6 bits) as
            // 00000011 11112222 22333333

            c[0] = (char) ((b[i] & 0xFC) >> 2);
            c[1] = (char) ((b[i] & 0x03) << 4);
            if (remaining >= 2) {
                c[1] += (char) ((b[i+1] & 0xF0) >> 4);
                c[2] = (char) ((b[i+1] & 0x0F) << 2);
                if (remaining >= 3) {
                    c[2] += (char) ((b[i+2] & 0xC0) >> 6);
                    c[3] = (char) (b[i+2] & 0x3F);
                } else {
                    c[3] = 64;
                }
            } else {
                c[2] = 64;
                c[3] = 64;
            }

            // Convert to base64 chars
            for(int j = 0; j < 4; j++) {
                if (c[j] < 26) {
                    c[j] += 'A';
                } else if (c[j] < 52) {
                    c[j] = (char) (c[j] - 26 + 'a');
                } else if (c[j] < 62) {
                    c[j] = (char) (c[j] - 52 + '0');
                } else if (c[j] == 62) {
                    c[j] = '+';
                } else if (c[j] == 63) {
                    c[j] = '/';
                } else {
                    c[j] = '=';
                }
            }

            sb.append(c);
            i += 3;
            remaining -= 3;
        }

        return sb.toString();
    }

    /**
     * Convenience method for setting the given entry as a double.
     * The double is converted with <code>Double.toString(double)</code>
     * and then stored in the preference entry as that string.
     *
     * @exception NullPointerException if the key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putDouble(String key, double value) {
        put(key, Double.toString(value));
    }

    /**
     * Convenience method for setting the given entry as a float.
     * The float is converted with <code>Float.toString(float)</code>
     * and then stored in the preference entry as that string.
     *
     * @exception NullPointerException if the key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putFloat(String key, float value) {
        put(key, Float.toString(value));
    }

    /**
     * Convenience method for setting the given entry as an integer.
     * The integer is converted with <code>Integer.toString(int)</code>
     * and then stored in the preference entry as that string.
     *
     * @exception NullPointerException if the key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putInt(String key, int value) {
        put(key, Integer.toString(value));
    }

    /**
     * Convenience method for setting the given entry as a long.
     * The long is converted with <code>Long.toString(long)</code>
     * and then stored in the preference entry as that string.
     *
     * @exception NullPointerException if the key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void putLong(String key, long value) {
        put(key, Long.toString(value));
    }

    /**
     * Removes the preferences entry from this preferences node.
     * <p>     
     * The result will be immediately visible in this VM, but may not be
     * immediately written to the backing store.
     * <p>
     * This implementation checks that the key is not larger then 80
     * characters, gets the lock of this node, checks that the node has
     * not been removed and calls <code>removeSpi</code> with the given key.
     *
     * @exception NullPointerException if the key is null
     * @exception IllegalArgumentException if the key length is to large
     * @exception IllegalStateException when this node has been removed
     */
    public void remove(String key) {
        if (key.length() > MAX_KEY_LENGTH)
            throw new IllegalArgumentException(key);

        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node removed");

            removeSpi(key);

            if (preferenceListeners != null)
              fire(new PreferenceChangeEvent(this, key, null));
        }
    }

    /**
     * Removes all entries from this preferences node. May need access to the
     * backing store to get and clear all entries.
     * <p>
     * The result will be immediately visible in this VM, but may not be
     * immediatly written to the backing store.
     * <p>
     * This implementation locks this node, checks that the node has not been
     * removed and calls <code>keys()</code> to get a complete array of keys
     * for this node. For every key found <code>removeSpi()</code> is called.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public void clear() throws BackingStoreException {
        synchronized(lock) {
            if (isRemoved())
                throw new IllegalStateException("Node Removed");

            String[] keys = keys();
            for (int i = 0; i < keys.length; i++) {
                removeSpi(keys[i]);
            }
        }
    }

    /**
     * Writes all preference changes on this and any subnode that have not
     * yet been written to the backing store. This has no effect on the
     * preference entries in this VM, but it makes sure that all changes
     * are visible to other programs (other VMs might need to call the
     * <code>sync()</code> method to actually see the changes to the backing
     * store.
     * <p>
     * Locks this node, calls the <code>flushSpi()</code> method, gets all
     * the (cached - already existing in this VM) subnodes and then calls
     * <code>flushSpi()</code> on every subnode with this node unlocked and
     * only that particular subnode locked.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     */
    public void flush() throws BackingStoreException {
        flushNode(false);
    }

    /**
     * Writes and reads all preference changes to and from this and any
     * subnodes. This makes sure that all local changes are written to the
     * backing store and that all changes to the backing store are visible
     * in this preference node (and all subnodes).
     * <p>
     * Checks that this node is not removed, locks this node, calls the
     * <code>syncSpi()</code> method, gets all the subnodes and then calls
     * <code>syncSpi()</code> on every subnode with this node unlocked and
     * only that particular subnode locked.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public void sync() throws BackingStoreException {
        flushNode(true);
    }
    

    /**
     * Private helper method that locks this node and calls either
     * <code>flushSpi()</code> if <code>sync</code> is false, or
     * <code>flushSpi()</code> if <code>sync</code> is true. Then it gets all
     * the currently cached subnodes. For every subnode it calls this method
     * recursively with this node no longer locked.
     * <p>
     * Called by either <code>flush()</code> or <code>sync()</code>
     */
    private void flushNode(boolean sync) throws BackingStoreException {
        String[] keys = null;
        synchronized(lock) {
            if (sync) {
                syncSpi();
            } else {
                flushSpi();
            }
            keys = (String[]) childCache.keySet().toArray(new String[]{});
        }

        if (keys != null) {
            for (int i = 0; i < keys.length; i++) {
                // Have to lock this node again to access the childCache
                AbstractPreferences subNode;
                synchronized(lock) {
                    subNode = (AbstractPreferences) childCache.get(keys[i]);
                }

                // The child could already have been removed from the cache
                if (subNode != null) {
                    subNode.flushNode(sync);
                }
            }
        }
    }

    /**
     * Removes this and all subnodes from the backing store and clears all
     * entries. After removal this instance will not be useable (except for
     * a few methods that don't throw a <code>InvalidStateException</code>),
     * even when a new node with the same path name is created this instance
     * will not be usable again.
     * <p>
     * Checks that this is not a root node. If not it locks the parent node,
     * then locks this node and checks that the node has not yet been removed.
     * Then it makes sure that all subnodes of this node are in the child cache,
     * by calling <code>childSpi()</code> on any children not yet in the cache.
     * Then for all children it locks the subnode and removes it. After all
     * subnodes have been purged the child cache is cleared, this nodes removed
     * flag is set and any listeners are called. Finally this node is removed
     * from the child cache of the parent node.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has already been removed
     * @exception UnsupportedOperationException if this is a root node
     */
    public void removeNode() throws BackingStoreException {
        // Check if it is a root node
        if (parent == null)
            throw new UnsupportedOperationException("Cannot remove root node");

        synchronized (parent.lock) {
            synchronized(this.lock) {
                if (isRemoved())
                    throw new IllegalStateException("Node Removed");

                purge();
            }
            parent.childCache.remove(name);
        }
    }

    /**
     * Private helper method used to completely remove this node.
     * Called by <code>removeNode</code> with the parent node and this node
     * locked.
     * <p>
     * Makes sure that all subnodes of this node are in the child cache,
     * by calling <code>childSpi()</code> on any children not yet in the
     * cache. Then for all children it locks the subnode and calls this method
     * on that node. After all subnodes have been purged the child cache is
     * cleared, this nodes removed flag is set and any listeners are called.
     */
    private void purge() throws BackingStoreException
    {
        // Make sure all children have an AbstractPreferences node in cache
        String children[] = childrenNamesSpi();
        for (int i = 0; i < children.length; i++) {
            if (childCache.get(children[i]) == null)
                childCache.put(children[i], childSpi(children[i]));
        }

        // purge all children
        Iterator i = childCache.values().iterator();
        while (i.hasNext()) {
            AbstractPreferences node = (AbstractPreferences) i.next();
            synchronized(node.lock) {
                node.purge();
            }
        }

        // Cache is empty now
        childCache.clear();

        // remove this node
        removeNodeSpi();
        removed = true;

        if (nodeListeners != null)
          fire(new NodeChangeEvent(parent, this), false);
    }

    // listener methods

    /**
     * Add a listener which is notified when a sub-node of this node
     * is added or removed.
     * @param listener the listener to add
     */
    public void addNodeChangeListener(NodeChangeListener listener)
    {
      synchronized (lock)
        {
          if (isRemoved())
            throw new IllegalStateException("node has been removed");
          if (listener == null)
            throw new NullPointerException("listener is null");
          if (nodeListeners == null)
            nodeListeners = new ArrayList<NodeChangeListener>();
          nodeListeners.add(listener);
        }
    }

    /**
     * Add a listener which is notified when a value in this node
     * is added, changed, or removed.
     * @param listener the listener to add
     */
    public void addPreferenceChangeListener(PreferenceChangeListener listener)
    {
      synchronized (lock)
        {
          if (isRemoved())
            throw new IllegalStateException("node has been removed");
          if (listener == null)
            throw new NullPointerException("listener is null");
          if (preferenceListeners == null)
            preferenceListeners = new ArrayList<PreferenceChangeListener>();
          preferenceListeners.add(listener);
        }
    }

    /**
     * Remove the indicated node change listener from the list of
     * listeners to notify.
     * @param listener the listener to remove
     */
    public void removeNodeChangeListener(NodeChangeListener listener)
    {
      synchronized (lock)
        {
          if (isRemoved())
            throw new IllegalStateException("node has been removed");
          if (listener == null)
            throw new NullPointerException("listener is null");
          if (nodeListeners != null)
            nodeListeners.remove(listener);
        }
    }

    /**
     * Remove the indicated preference change listener from the list of
     * listeners to notify.
     * @param listener the listener to remove
     */
    public void removePreferenceChangeListener (PreferenceChangeListener listener)
    {
      synchronized (lock)
        {
          if (isRemoved())
            throw new IllegalStateException("node has been removed");
          if (listener == null)
            throw new NullPointerException("listener is null");
          if (preferenceListeners != null)
            preferenceListeners.remove(listener);
        }
    }

    /**
     * Send a preference change event to all listeners.  Note that
     * the caller is responsible for holding the node's lock, and
     * for checking that the list of listeners is not null.
     * @param event the event to send
     */
    private void fire(final PreferenceChangeEvent event)
    {
      Iterator it = preferenceListeners.iterator();
      while (it.hasNext())
        {
          final PreferenceChangeListener l = (PreferenceChangeListener) it.next();
          EventDispatcher.dispatch(new Runnable()
                                   {
                                     public void run()
                                     {
                                       l.preferenceChange(event);
                                     }
                                   });
        }
    }

    /**
     * Send a node change event to all listeners.  Note that
     * the caller is responsible for holding the node's lock, and
     * for checking that the list of listeners is not null.
     * @param event the event to send
     */
    private void fire(final NodeChangeEvent event, final boolean added)
    {
      Iterator it = nodeListeners.iterator();
      while (it.hasNext())
        {
          final NodeChangeListener l = (NodeChangeListener) it.next();
          EventDispatcher.dispatch(new Runnable()
                                   {
                                     public void run()
                                     {
                                       if (added)
                                         l.childAdded(event);
                                       else
                                         l.childRemoved(event);
                                     }
                                   });
        }
    }

    // abstract spi methods

    /**
     * Returns the names of the sub nodes of this preference node.
     * This method only has to return any not yet cached child names,
     * but may return all names if that is easier. It must not return
     * null when there are no children, it has to return an empty array
     * in that case. Since this method must consult the backing store to
     * get all the sub node names it may throw a BackingStoreException.
     * <p>
     * Called by <code>childrenNames()</code> with this node locked.
     */
    protected abstract String[] childrenNamesSpi() throws BackingStoreException;

    /**
     * Returns a child note with the given name.
     * This method is called by the <code>node()</code> method (indirectly
     * through the <code>getNode()</code> helper method) with this node locked
     * if a sub node with this name does not already exist in the child cache.
     * If the child node did not aleady exist in the backing store the boolean
     * field <code>newNode</code> of the returned node should be set.
     * <p>
     * Note that this method should even return a non-null child node if the
     * backing store is not available since it may not throw a
     * <code>BackingStoreException</code>.
     */
    protected abstract AbstractPreferences childSpi(String name);

    /**
     * Returns an (possibly empty) array with all the keys of the preference
     * entries of this node.
     * <p>
     * Called by <code>keys()</code> with this node locked if this node has
     * not been removed. May throw an exception when the backing store cannot
     * be accessed.
     *
     * @exception BackingStoreException when the backing store cannot be     
     *            reached
     */
    protected abstract String[] keysSpi() throws BackingStoreException;
     
    /**
     * Returns the value associated with the key in this preferences node or
     * null when the key does not exist in this preferences node.
     * <p>
     * Called by <code>key()</code> with this node locked after checking that
     * key is valid, not null and that the node has not been removed.
     * <code>key()</code> will catch any exceptions that this method throws.
     */
    protected abstract String getSpi(String key);

    /**
     * Sets the value of the given preferences entry for this node.
     * The implementation is not required to propagate the change to the
     * backing store immediately. It may not throw an exception when it tries
     * to write to the backing store and that operation fails, the failure
     * should be registered so a later invocation of <code>flush()</code>
     * or <code>sync()</code> can signal the failure.
     * <p>
     * Called by <code>put()</code> with this node locked after checking that
     * key and value are valid and non-null.
     */
    protected abstract void putSpi(String key, String value);

    /**
     * Removes the given key entry from this preferences node.
     * The implementation is not required to propagate the change to the
     * backing store immediately.  It may not throw an exception when it tries
     * to write to the backing store and that operation fails, the failure
     * should be registered so a later invocation of <code>flush()</code>
     * or <code>sync()</code> can signal the failure.
     * <p>
     * Called by <code>remove()</code> with this node locked after checking
     * that the key is valid and non-null.
     */
    protected abstract void removeSpi(String key);

    /**
     * Writes all entries of this preferences node that have not yet been
     * written to the backing store and possibly creates this node in the
     * backing store, if it does not yet exist. Should only write changes to
     * this node and not write changes to any subnodes.
     * Note that the node can be already removed in this VM. To check if
     * that is the case the implementation can call <code>isRemoved()</code>.
     * <p>
     * Called (indirectly) by <code>flush()</code> with this node locked.
     */
    protected abstract void flushSpi() throws BackingStoreException;

    /**
     * Writes all entries of this preferences node that have not yet been
     * written to the backing store and reads any entries that have changed
     * in the backing store but that are not yet visible in this VM.
     * Should only sync this node and not change any of the subnodes.
     * Note that the node can be already removed in this VM. To check if
     * that is the case the implementation can call <code>isRemoved()</code>.
     * <p>
     * Called (indirectly) by <code>sync()</code> with this node locked.
     */
    protected abstract void syncSpi() throws BackingStoreException;

    /**
     * Clears this node from this VM and removes it from the backing store.
     * After this method has been called the node is marked as removed.
     * <p>
     * Called (indirectly) by <code>removeNode()</code> with this node locked
     * after all the sub nodes of this node have already been removed.
     */
    protected abstract void removeNodeSpi() throws BackingStoreException;
}
