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