/* Preferences -- Preference node containing key value entries and subnodes
   Copyright (C) 2001, 2004, 2005, 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.classpath.ServiceFactory;
import gnu.java.util.prefs.NodeReader;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.util.Iterator;

/**
 * Preference node containing key value entries and subnodes.
 * <p>
 * There are two preference node trees, a system tree which can be accessed
 * by calling <code>systemRoot()</code> containing system preferences usefull
 * for all users, and a user tree that can be accessed by calling
 * <code>userRoot()</code> containing preferences that can differ between
 * different users. How different users are identified is implementation
 * depended. It can be determined by Thread, Access Control Context or Subject.
 * <p>
 * This implementation uses the "java.util.prefs.PreferencesFactory" system
 * property to find a class that implement <code>PreferencesFactory</code>
 * and initialized that class (if it has a public no arguments contructor)
 * to get at the actual system or user root. If the system property is not set,
 * or the class cannot be initialized it uses the default implementation
 * <code>gnu.java.util.prefs.FileBasedFactory</code>.
 * <p>
 * Besides the two static method above to get the roots of the system and user
 * preference node trees there are also two convenience methods to access the
 * default preference node for a particular package an object is in. These are
 * <code>userNodeForPackage()</code> and <code>systemNodeForPackage()</code>.
 * Both methods take an Object as an argument so accessing preferences values
 * can be as easy as calling <code>Preferences.userNodeForPackage(this)</code>.
 * <p>
 * Note that if a security manager is installed all static methods check for
 * <code>RuntimePermission("preferences")</code>. But if this permission is
 * given to the code then it can access and change all (user) preference nodes
 * and entries. So you should be carefull not to store to sensitive information
 * or make security decissions based on preference values since there is no
 * more fine grained control over what preference values can be changed once
 * code has been given the correct runtime permission.
 * <p>
 * XXX
 *
 * @since 1.4
 * @author Mark Wielaard (mark@klomp.org)
 */
public abstract class Preferences {

    // Static Fields

    /**
     * Default PreferencesFactory class used when the system property
     * "java.util.prefs.PreferencesFactory" is not set.
     */
    private static final String defaultFactoryClass
        = "gnu.java.util.prefs.FileBasedFactory";

    /** Permission needed to access system or user root. */
    private static final Permission prefsPermission
        = new RuntimePermission("preferences");

    /**
     * The preferences factory object that supplies the system and user root.
     * Set and returned by the getFactory() method.
     */
    private static PreferencesFactory factory;

    /** Maximum node name length. 80 characters. */
    public static final int MAX_NAME_LENGTH = 80;

    /** Maximum entry key length. 80 characters. */
    public static final int MAX_KEY_LENGTH = 80;

    /** Maximum entry value length. 8192 characters. */
    public static final int MAX_VALUE_LENGTH = 8192;

    // Constructors

    /**
     * Creates a new Preferences node. Can only be used by subclasses.
     * Empty implementation.
     */
    protected Preferences() {}

    // Static methods

    /**
     * Returns the system preferences root node containing usefull preferences
     * for all users. It is save to cache this value since it should always
     * return the same preference node.
     *
     * @return the root system preference node
     * @exception SecurityException when a security manager is installed and
     * the caller does not have <code>RuntimePermission("preferences")</code>.
     */
    public static Preferences systemRoot() throws SecurityException {
        // Get the preferences factory and check for permission
        PreferencesFactory factory = getFactory();

        return factory.systemRoot();
    }

    /**
     * Returns the user preferences root node containing preferences for the
     * the current user. How different users are identified is implementation
     * depended. It can be determined by Thread, Access Control Context or
     * Subject.
     *
     * @return the root user preference node
     * @exception SecurityException when a security manager is installed and
     * the caller does not have <code>RuntimePermission("preferences")</code>.
     */
    public static Preferences userRoot() throws SecurityException {
        // Get the preferences factory and check for permission
        PreferencesFactory factory = getFactory();
        return factory.userRoot();
    }

    /**
     * Private helper method for <code>systemRoot()</code> and
     * <code>userRoot()</code>. Checks security permission and instantiates the
     * correct factory if it has not yet been set.
     * <p>
     * When the preferences factory has not yet been set this method first
     * tries to get the system propery "java.util.prefs.PreferencesFactory"
     * and tries to initializes that class. If the system property is not set
     * or initialization fails it returns an instance of the default factory
     * <code>gnu.java.util.prefs.FileBasedPreferencesFactory</code>.
     *
     * @return the preferences factory to use
     * @exception SecurityException when a security manager is installed and
     * the caller does not have <code>RuntimePermission("preferences")</code>.
     */
    private static PreferencesFactory getFactory() throws SecurityException {

        // First check for permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(prefsPermission);
        }

        // Get the factory
        if (factory == null) {
            // Caller might not have enough permissions
            factory = AccessController.doPrivileged(
                        new PrivilegedAction<PreferencesFactory>() {
                            public PreferencesFactory run() {
                                PreferencesFactory pf = null;
                                String className = System.getProperty
                                    ("java.util.prefs.PreferencesFactory");
                                if (className != null) {
                                    try {
                                        Class fc = Class.forName(className);
                                        Object o = fc.newInstance();
                                        pf = (PreferencesFactory) o;
                                    } catch (ClassNotFoundException cnfe)
                                        {/*ignore*/}
                                    catch (InstantiationException ie)
                                        {/*ignore*/}
                                    catch (IllegalAccessException iae)
                                        {/*ignore*/}
                                    catch (ClassCastException cce)
                                        {/*ignore*/}
                                }
                                return pf;
                            }
                        });

            // Still no factory? Try to see if we have one defined
            // as a System Preference
            if (factory == null)
              {
                Iterator iter = ServiceFactory.lookupProviders
                    (PreferencesFactory.class, null);

                if (iter != null && iter.hasNext())
                  factory = (PreferencesFactory) iter.next();
              }

            // Still no factory? Use our default.
            if (factory == null)
              {
                try
                  {
                    Class cls = Class.forName (defaultFactoryClass);
                    factory = (PreferencesFactory) cls.newInstance();
                  }
                catch (Exception e)
                  {
                    throw new RuntimeException ("Couldn't load default factory"
                        + " '"+ defaultFactoryClass +"'", e);
                  }
              }

        }

        return factory;
    }

    /**
     * Returns the system preferences node for the package of a class.
     * The package node name of the class is determined by dropping the
     * final component of the fully qualified class name and
     * changing all '.' to '/' in the package name. If the class of the
     * object has no package then the package node name is "&lt;unnamed&gt;".
     * The returned node is <code>systemRoot().node(packageNodeName)</code>.
     *
     * @param c Object whose default system preference node is requested
     * @returns system preferences node that should be used by class c
     * @exception SecurityException when a security manager is installed and
     * the caller does not have <code>RuntimePermission("preferences")</code>.
     */
    public static Preferences systemNodeForPackage(Class<?> c)
            throws SecurityException
    {
        return nodeForPackage(c, systemRoot());
    }

    /**
     * Returns the user preferences node for the package of a class.
     * The package node name of the class is determined by dropping the
     * final component of the fully qualified class name and
     * changing all '.' to '/' in the package name. If the class of the
     * object has no package then the package node name is "&lt;unnamed&gt;".
     * The returned node is <code>userRoot().node(packageNodeName)</code>.
     *
     * @param c Object whose default userpreference node is requested
     * @returns userpreferences node that should be used by class c
     * @exception SecurityException when a security manager is installed and
     * the caller does not have <code>RuntimePermission("preferences")</code>.
     */
    public static Preferences userNodeForPackage(Class<?> c)
            throws SecurityException
    {
        return nodeForPackage(c, userRoot());
    }

    /**
     * Private helper method for <code>systemNodeForPackage()</code> and
     * <code>userNodeForPackage()</code>. Given the correct system or user
     * root it returns the correct Preference node for the package node name
     * of the given object.
     */
    private static Preferences nodeForPackage(Class c, Preferences root) {
        // Get the package path
        String className = c.getName();
        String packagePath;
        int index = className.lastIndexOf('.');
        if(index == -1) {
            packagePath = "<unnamed>";
        } else {
            packagePath = className.substring(0,index).replace('.','/');
        }

        return root.node(packagePath);
    }

    /**
     * Import preferences from the given input stream.  This expects
     * preferences to be represented in XML as emitted by
     * {@link #exportNode(OutputStream)} and
     * {@link #exportSubtree(OutputStream)}.
     * @throws IOException if there is an error while reading
     * @throws InvalidPreferencesFormatException if the XML is not properly
     * formatted
     */
    public static void importPreferences(InputStream is)
                                    throws InvalidPreferencesFormatException,
                                           IOException
    {
        PreferencesFactory factory = getFactory();
        NodeReader reader = new NodeReader(is, factory);
        reader.importPreferences();
    }

    // abstract methods (identification)

    /**
     * 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 name is "" and its absolute path name is "/".
     */
    public abstract String absolutePath();

    /**
     * Returns true if this node comes from the user preferences tree, false
     * if it comes from the system preferences tree.
     */
    public abstract boolean isUserNode();

    /**
     * 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 abstract String name();

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

    // abstract methods (navigation)

    /**
     * Returns all the direct sub nodes of this preferences node.
     * Needs access to the backing store to give a meaningfull answer.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException when this node has been removed
     */
    public abstract String[] childrenNames() throws BackingStoreException;

    /**
     * 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 '/').
     *
     * @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
     * then 80 characters long
     */
    public abstract Preferences node(String path);

    /**
     * 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 abstract boolean nodeExists(String path)
                                throws BackingStoreException;

    /**
     * Returns the parent preferences node of this node or null if this is
     * the root of the preferences tree.
     *
     * @exception IllegalStateException if this node has been removed
     */
    public abstract Preferences parent();

    // abstract methods (export)

    /**
     * Export this node, but not its descendants, as XML to the
     * indicated output stream.  The XML will be encoded using UTF-8
     * and will use a specified document type:<br>
     * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
     * @param os the output stream to which the XML is sent
     * @throws BackingStoreException if preference data cannot be read
     * @throws IOException if an error occurs while writing the XML
     * @throws IllegalStateException if this node or an ancestor has been removed
     */
    public abstract void exportNode(OutputStream os)
                                throws BackingStoreException,
                                       IOException;

    /**
     * Export this node and all its descendants as XML to the
     * indicated output stream.  The XML will be encoded using UTF-8
     * and will use a specified document type:<br>
     * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
     * @param os the output stream to which the XML is sent
     * @throws BackingStoreException if preference data cannot be read
     * @throws IOException if an error occurs while writing the XML
     * @throws IllegalStateException if this node or an ancestor has been removed
     */
    public abstract void exportSubtree(OutputStream os)
                                throws BackingStoreException,
                                       IOException;

    // abstract methods (preference entry manipulation)

    /**
     * Returns an (possibly empty) array with all the keys of the preference
     * entries of this node.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public abstract String[] keys() throws BackingStoreException;

    /**
     * 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.
     *
     * @exception IllegalArgumentException if key is larger then 80 characters
     * @exception IllegalStateException if this node has been removed
     * @exception NullPointerException if key is null
     */
    public abstract String get(String key, String 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 abstract boolean getBoolean(String key, boolean 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 abstract byte[] getByteArray(String key, byte[] defaultVal);

    /**
     * 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 abstract double getDouble(String key, double 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 abstract float getFloat(String key, float 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 abstract int getInt(String key, int 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 abstract long getLong(String key, long 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 immediatly visible in this VM, but may not be
     * immediatly written to the backing store.
     *
     * @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 abstract void put(String key, String 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 abstract void putBoolean(String key, boolean 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 abstract void putByteArray(String key, byte[] value);

    /**
     * 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 abstract void putDouble(String key, double 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 abstract void putFloat(String key, float 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 abstract void putInt(String key, int 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 abstract void putLong(String key, long value);

    /**
     * Removes the preferences entry from this preferences node.
     * <p>
     * The result will be immediatly visible in this VM, but may not be
     * immediatly written to the backing store.
     *
     * @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 abstract void remove(String key);

    // abstract methods (preference node manipulation)

    /**
     * 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 immediatly visible in this VM, but may not be
     * immediatly written to the backing store.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public abstract void clear() throws BackingStoreException;

    /**
     * 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.
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public abstract void flush() throws BackingStoreException;

    /**
     * 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).
     *
     * @exception BackingStoreException when the backing store cannot be
     *            reached
     * @exception IllegalStateException if this node has been removed
     */
    public abstract void sync() throws BackingStoreException;

    /**
     * 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. The root (system or user) may never be removed.
     * <p>
     * Note that according to the specification an implementation may delay
     * removal of the node from the backing store till the <code>flush()</code>
     * method is called. But the <code>flush()</code> method may throw a
     * <code>IllegalStateException</code> when the node has been removed.
     * So most implementations will actually remove the node and any subnodes
     * from the backing store immediatly.
     *
     * @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 abstract void removeNode() throws BackingStoreException;

    // abstract methods (listeners)

    public abstract void addNodeChangeListener(NodeChangeListener listener);

    public abstract void addPreferenceChangeListener
                            (PreferenceChangeListener listener);

    public abstract void removeNodeChangeListener(NodeChangeListener listener);

    public abstract void removePreferenceChangeListener
                            (PreferenceChangeListener listener);
}
