/* GConfBasedPreferences.java -- GConf based Preferences implementation
 Copyright (C) 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 gnu.java.util.prefs;

import gnu.java.util.prefs.gconf.GConfNativePeer;

import java.security.Permission;

import java.util.List;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;

/**
 * This is a GConf based preference implementation which writes the preferences
 * as GConf key-value pairs. System Root is defined to be the
 * <code>"/system"</code> directory of GConf for the current user, while User
 * Root is <code>"/apps/java"</code>. These defaults can be modified by
 * defining two system properties:<br />
 * <br />
 * User Root:<br />
 * <br />
 *
 * <pre>
 * gnu.java.util.prefs.gconf.user_root
 * </pre>
 *
 * <br />
 * <br />
 * and System Root:<br />
 * <br />
 *
 * <pre>
 * gnu.java.util.prefs.gconf.system_root
 * </pre>
 *
 * <br />
 *
 * @author Mario Torre <neugens@limasoftware.net>
 */
public class GConfBasedPreferences
    extends AbstractPreferences
{
  /** Get access to Runtime permission */
  private static final Permission PERMISSION
    = new RuntimePermission("preferences");

  /** CGonf client backend */
  private static GConfNativePeer backend = new GConfNativePeer();

  /** Default user root path */
  private static final String DEFAULT_USER_ROOT = "/apps/classpath";

  /** Default system root path */
  private static final String DEFAULT_SYSTEM_ROOT = "/system";

  /** current node full path */
  private String node = "";

  /** True if this is a preference node in the user tree, false otherwise. */
  private final boolean isUser;

  /**
   * Creates a preference root user node.
   */
  public GConfBasedPreferences()
  {
    this(true);
  }

  /**
   * Creates a preference root node. When <code>isUser</code> is true it will
   * be user node otherwise it will be a system node.
   */
  public GConfBasedPreferences(boolean isUser)
  {
    this(null, "", isUser);
  }

  /**
   * Creates a new preference node given a parent node and a name, which has to
   * be relative to its parent. When <code>isUser</code> is true it will be user
   * node otherwise it will be a system node.
   *
   * @param parent The parent node of this newly created node.
   * @param name A name relative to the parent node.
   * @param isUser Set to <code>true</code> initializes this node to be
   * a user node, <code>false</code> initialize it to be a system node.
   */
  public GConfBasedPreferences(AbstractPreferences parent, String name,
                               boolean isUser)
  {
    super(parent, name);
    this.isUser = isUser;

    // stores the fully qualified name of this node
    String absolutePath = this.absolutePath();
    if (absolutePath != null && absolutePath.endsWith("/"))
      {
        absolutePath = absolutePath.substring(0, absolutePath.length() - 1);
      }

    // strip invalid characters
    // please, note that all names are unescaped into the native peer
    int index = absolutePath.lastIndexOf('/');
    if (index > -1)
      {
        absolutePath = absolutePath.substring(0, index + 1);
        absolutePath = absolutePath + GConfNativePeer.escapeString(name);
      }

    this.node = this.getRealRoot(isUser) + absolutePath;

    boolean nodeExist = backend.nodeExist(this.node);

    this.newNode = !nodeExist;
  }

  /**
   * Returns a child node with the given name.
   * If the child node does not exists, it will be created.
   *
   * @param name The name of the requested node.
   * @return A new reference to the node, creating the node if it is necessary.
   */
  protected AbstractPreferences childSpi(String name)
  {
    // we don't check anything here, if the node is a new node this will be
    // detected in the constructor, so we simply return a new reference to
    // the requested node.

    GConfBasedPreferences preferenceNode
      = new GConfBasedPreferences(this, name, this.isUser);

    return preferenceNode;
  }

  /**
   * Returns an array of names of the children of this preference node.
   * If the current node does not have children, the returned array will be
   * of <code>size</code> 0 (that is, not <code>null</code>).
   *
   * @return A <code>String</code> array of names of children of the current
   * node.
   * @throws BackingStoreException if this operation cannot be completed.
   */
  protected String[] childrenNamesSpi() throws BackingStoreException
  {
    List<String> nodeList = backend.getChildrenNodes(this.node);
    String[] nodes = new String[nodeList.size()];
    nodeList.toArray(nodes);

    return nodes;
  }

  /**
   * Suggest a flush to the backend. Actually, this is only a suggestion as
   * GConf handles this for us asynchronously. More over, both sync and flush
   * have the same meaning in this class, so calling sync has exactly the same
   * effect.
   *
   * @see #sync
   * @throws BackingStoreException if this operation cannot be completed.
   */
  public void flush() throws BackingStoreException
  {
    backend.suggestSync();
  }

  /**
   * Request a flush.
   *
   * @see #flush
   * @throws BackingStoreException if this operation cannot be completed.
   */
  protected void flushSpi() throws BackingStoreException
  {
    this.flush();
  }

  /**
   * Returns all of the key in this preference node.
   * If the current node does not have preferences, the returned array will be
   * of size zero.
   *
   * @return A <code>String</code> array of keys stored under the current
   * node.
   * @throws BackingStoreException if this operation cannot be completed.
   */
  protected String[] keysSpi() throws BackingStoreException
  {
    List<String> keyList = backend.getKeys(this.node);
    String[] keys = new String[keyList.size()];
    keyList.toArray(keys);

    return keys;
  }

  /**
   * Does a recursive postorder traversal of the preference tree, starting from
   * the given directory invalidating every preference found in the node.
   *
   * @param directory The name of the starting directory (node)
   */
  private void postorderRemove(String directory)
  {
    try
      {
        // gets the listing of directories in this node
        List<String> dirs = backend.getChildrenNodes(directory);

        if (dirs.size() != 0)
          {
            for (String currentDir : dirs)
              {
                // recursive search inside this directory
                postorderRemove(currentDir);
              }
          }

        // remove all the keys associated to this directory
        List<String> entries = backend.getKeys(directory);

        if (entries.size() != 0)
          {
            for (String key : entries)
              {
                this.removeSpi(key);
              }
          }
      }
    catch (BackingStoreException ex)
      {
        /* ignore */
      }
  }

  /**
   * Stores the given key-value pair into this preference node.
   *
   * @param key The key of this preference.
   * @param value The value of this preference.
   */
  protected void putSpi(String key, String value)
  {
    backend.setString(this.getGConfKey(key), value);
  }

  /**
   * Removes this preference node, including all its children.
   * Also removes the preferences associated.
   */
  protected void removeNodeSpi() throws BackingStoreException
  {
    this.postorderRemove(this.node);
    this.flush();
  }

  /**
   * Removes the given key from this preference node.
   * If the key does not exist, no operation is performed.
   *
   * @param key The key to remove.
   */
  protected void removeSpi(String key)
  {
    backend.unset(this.getGConfKey(key));
  }

  /**
   * Suggest a sync to the backend. Actually, this is only a suggestion as GConf
   * handles this for us asynchronously. More over, both sync and flush have the
   * same meaning in this class, so calling flush has exactly the same effect.
   *
   * @see #flush
   * @throws BackingStoreException if this operation cannot be completed due to
   *           a failure in the backing store, or inability to communicate with
   *           it.
   */
  public void sync() throws BackingStoreException
  {
    this.flush();
  }

  /**
   * Request a sync.
   *
   * @see #sync
   * @throws BackingStoreException if this operation cannot be completed due to
   *           a failure in the backing store, or inability to communicate with
   *           it.
   */
  protected void syncSpi() throws BackingStoreException
  {
    this.sync();
  }

  /**
   * Returns the value of the given key.
   * If the keys does not have a value, or there is an error in the backing
   * store, <code>null</code> is returned instead.
   *
   * @param key The key to retrieve.
   * @return The value associated with the given key.
   */
  protected String getSpi(String key)
  {
    return backend.getKey(this.getGConfKey(key));
  }

  /**
   * Returns <code>true</code> if this preference node is a user node,
   * <code>false</code> if is a system preference node.
   *
   * @return <code>true</code> if this preference node is a user node,
   * <code>false</code> if is a system preference node.
   */
  public boolean isUserNode()
  {
    return this.isUser;
  }

  /*
   * PRIVATE METHODS
   */

  /**
   * Builds a GConf key string suitable for operations on the backend.
   *
   * @param key The key to convert into a valid GConf key.
   * @return A valid Gconf key.
   */
  private String getGConfKey(String key)
  {
    String nodeName = "";

    // strip key
    // please, note that all names are unescaped into the native peer
    key = GConfNativePeer.escapeString(key);

    if (this.node.endsWith("/"))
      {
        nodeName = this.node + key;
      }
    else
      {
        nodeName = this.node + "/" + key;
      }

    return nodeName;
  }

  /**
   * Builds the root node to use for this preference.
   *
   * @param isUser Defines if this node is a user (<code>true</code>) or system
   * (<code>false</code>) node.
   * @return The real root of this preference tree.
   */
  private String getRealRoot(boolean isUser)
  {
    // not sure about this, we should have already these permissions...
    SecurityManager security = System.getSecurityManager();

    if (security != null)
      {
        security.checkPermission(PERMISSION);
      }

    String root = null;

    if (isUser)
      {
        root = System.getProperty("gnu.java.util.prefs.gconf.user_root",
                                  DEFAULT_USER_ROOT);
      }
    else
      {
        root = System.getProperty("gnu.java.util.prefs.gconf.system_root",
                                  DEFAULT_SYSTEM_ROOT);
      }

    return root;
  }
}
