/* 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.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 childCache = new HashMap();

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

    /**
     * A list of all the registered PreferenceChangeListener objects.
     */
    private ArrayList 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()
    {
      return (AbstractPreferences[]) childCache.values().toArray();
    }

    /**
     * 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 childrenNames = new TreeSet();

            // 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();
          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();
          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;
}
