Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: persistent data



Lyderic Landry wrote:

>1. I have a class in a package called com.example.package
>...
>3. Now if I remove the node with prefs.removeNode():
> - On Mac: this actually removes the file in $HOME/Library/Preferences/
>com.example.package.plist and the entry in $HOME/Library/Preferences/
>com.apple.java.util.prefs.plist (this is perfect)
> - On Windows: this removes the last node (called 'package') but not the
>above tree (i.e. 'com\example') (this could be better and remove the whole
>thing).

You should file a bug with Sun against the Windows version of Java. If you
don't get a fix, you should at least get an explanation or rationale for
the observed behavior.

You might also want to look inside:
  $HOME/Library/Preferences/com.apple.java.util.prefs.plist

because the removal may not be as complete as you think.  I haven't looked,
but it's likely there's still a "/com/example/" node in that file, which
would correspond precisely to the observed Windows registry behavior.

If you want to remove "/com/example/", which I presume is your sole and
sovereign domain, then you should remove that node.  A smarter approach,
though, would be to only remove that node if it has no other children or
keys, applied recursively up the node-tree.  That way, when you release a
second app, removing the first one's prefs won't blindly kill all the prefs
stored for the second one.

It's not a huge task to use the Preferences API to write command-line
tools for inspecting and manipulating prefs-nodes.  Below is the source for
two such tools that I've been using for a while.  They work on Windows, too.
When replying, please remove unnecessarily quoted material.

  -- GG


#########
/*
** Written by Greg Guerin.
** Released into the public domain.
** No warranty, as-is, use at own risk.
*/

package tools;

import java.io.*;
import java.util.prefs.*;


/**
** Prefs is a command-line tool to list keys, values, and children of a prefs-node,
** or to set or remove keys.
** This tool cannot remove nodes.  To do that, use PrefsDelete, a related tool class.
**<p>
** Command args to Prefs are optional pref-node names.
** If no args, lists the root of both user-nodes and system-nodes.
**<p>
** Node names that start with "@" refer to system nodes, all others are user-nodes.
** Keys and values are displayed as "key=value", one per line.
** Child nodes are displayed as "/name", one per line, after all keys are listed.
**<p>
** To set a key on a node, use:
**   path/to/node.key=value
**<p>
** The key is separated from the node-path by ".".
** The assigned value is separated by "=".
** If the value is missing or empty (zero-length), the key is removed.
**<p>
** Because of the special meaning for certain characters [/.=],
** node-names and keys cannot contain '=', and keys cannot contain '/'.
** Node-names and keys MAY contain '.', but leaf-nodes cannot contain '.'.
*/

public class Prefs
{
  /** Prefix singifying "system node" */
  private static final String SYS = "@";


  /** Entry point. */
  public static void
  main( String[] args )
  {
    identify();

    // If no args, show info on root user-node and root system-node.
    if ( args.length == 0 )
      args = new String[] { "/", SYS + "/" };

    Prefs item = new Prefs();

    for ( int i = 0;  i < args.length;  ++i )
    {
      try
      {
        // If arg signifies an assignment, do it.
        if ( item.assignable( args[ i ] ) )
        {  item.set();  }

        // Show each node, whether it was assigned to or not.
        item.show();
      }
      catch ( Exception caught )
      {  caught.printStackTrace( System.out );  }
    }
  }



  private Preferences root;
  private String name;
  private String key, value;

  /** Create empty. */
  public
  Prefs()
  {  super();  }


  /**
  ** Assign name and root-node, decoding leading @ and any '=',
  ** returning T if it represents an assignment, F if not.
  */
  public boolean
  assignable( String str )
  {
    // Is it user or system node?
    this.root = Preferences.userRoot();
    if ( str.startsWith( SYS ) )
    {
      this.root = Preferences.systemRoot();
      str = str.substring( SYS.length() );
    }

    // Defaults signify "no assignment".
    this.key = this.value = null;

    // Is it an assignment or not?
    int sep = str.indexOf( '=' );
    if ( sep >= 0 )
    {
      // For value, use everything after '=', which may be empty to remove it.
      this.value = str.substring( sep + 1 );
      str = str.substring( 0, sep );

      // To separate key from node pathname, where pathname may contain '.',
      // find the FIRST '.' after  the LAST '/'.
      // Everything before that point is presumed to be node's pathname,
      // and everything after is presumed to be key.
      // There may be no slashes, but there MUST be a dot for there to be a key.
      // "No slashes" is simply "first-level node name", which has implicit initial "/".
      // A negative index is equivalent to 0: see API docs of String.indexOf(int,int).
      sep = str.lastIndexOf( '/' );  // LAST slash
      sep = str.indexOf( '.', sep );  // FIRST dot after LAST slash

      // If dot not found, key remains null.
      // If dot found but nothing follows, key will be "".
      // Otherwise key is what's after dot, which may itself contain ".".
      if ( sep >= 0 )
      {
        this.key = str.substring( sep + 1 );
        str = str.substring( 0, sep );
      }
    }

    // At this point, str is nothing but the node pathname.
    this.name = str;

    // Determine whether an assignable value is present or not.
    // Must have an assignable key.
    return ( key != null  &&  key.length() != 0 );
  }


  /** Show node, key/value pairs, and child names of referenced node. */
  public void
  show()
    throws BackingStoreException
  {
    if ( ! root.nodeExists( this.name ) )
    {
      tell( "No node for: " + this.name );
      return;
    }

    show( self() );
  }


  /** Set the node's key to the referenced value. */
  public void
  set()
    throws BackingStoreException
  {
    if ( key == null  ||  key.length() == 0 )
      return;

    Preferences self = self();

    if ( value == null  ||  value.length() == 0 )
      self.remove( key );
    else
      self.put( key, value );

    self.flush();
  }


  /** Remove the node ONLY if it signifies non-assignment. */
  public void
  remove()
    throws BackingStoreException
  {
    // Only remove node when key and value are both empty.
    if ( key == null  ||  key.length() == 0 )
    {
      if ( value == null  ||  value.length() == 0 )
      {
        Preferences self = self();
        self.removeNode();
        self.flush();

        tell( "Deleted " + self );
      }
    }
  }


  /** Return node referenced by self. */
  public Preferences
  self()
  {  return ( root.node( this.name ) );  }


  /** Describe the node. */
  public static void
  show( Preferences node )
    throws BackingStoreException
  {
    tell( node.toString() );

    String[] names = node.keys();
    for ( int i = 0;  i < names.length;  ++i )
    {
      String key = names[ i ];
      tell( "  " + key + "=" + node.get( key, "???" ) );
    }

    names = node.childrenNames();
    for ( int i = 0;  i < names.length;  ++i )
    {  tell( "  " + names[ i ] +"/"  );  }
  }


  /** Identify the platform. */
  public static void
  identify()
  {
    tell( "## " + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" )
        + ", Java " + System.getProperty( "java.runtime.version" ) );
  }


  /** Emit the text to stdout. */
  public static void
  tell( String text )
  {
    System.out.println( text );
  }

}

#########
/*
** Written by Greg Guerin.
** Released into the public domain.
** No warranty, as-is, use at own risk.
*/

package tools;

import java.io.*;
import java.util.prefs.*;


/**
** The class PrefsDelete is a tool that removes prefs-nodes.
** PrefsDelete has only a main() method.  It uses Prefs for everything else.
**<p>
** Command args to PrefsDelete are pref-node names.
** Node names that start with "@" refer to system nodes, all others are user-nodes.
*/

public class PrefsDelete
{
  /** Entry point. */
  public static void
  main( String[] args )
  {
    Prefs.identify();

    Prefs item = new Prefs();
    for ( int i = 0;  i < args.length;  ++i )
    {
      try
      {
        // If arg signifies an assignment, DON'T DELETE, but complain.
        if ( item.assignable( args[ i ] ) )
          Prefs.tell( "Incorrect syntax to delete: " + args[ i ] );
        else
          item.remove();
      }
      catch ( Exception caught )
      {  caught.printStackTrace( System.out );  }
    }
  }
}
#########


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden

This email sent to email@hidden



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.