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

