You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/15 15:57:17 UTC

svn commit: r386087 [30/45] - in /incubator/harmony/enhanced/classlib/trunk: make/ make/patternsets/ modules/jndi/ modules/jndi/META-INF/ modules/jndi/make/ modules/jndi/make/common/ modules/jndi/src/ modules/jndi/src/main/ modules/jndi/src/main/java/ ...

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,286 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * TODO some sync mechanism wich backend, Performance - check file edit date
+ */
+/*
+ * Default implementation of <code>AbstractPreferences</code> for Linux platform,
+ * using file system as back end. 
+ * 
+ * @since 1.4
+ */
+class FilePreferencesImpl extends AbstractPreferences {
+
+    /*
+     * --------------------------------------------------------------
+     * Constants
+     * --------------------------------------------------------------
+     */
+    //  user root preferences
+    static final Preferences userRoot;
+
+    //  system root preferences
+    static final Preferences systemRoot;
+
+    //prefs file name
+    private static final String prefsFileName = "prefs.xml"; //$NON-NLS-1$
+
+    //home directory for user prefs
+    static String USER_HOME;
+
+    //home directory for system prefs
+    static String SYSTEM_HOME;
+
+    /*
+     * --------------------------------------------------------------
+     * static init
+     * --------------------------------------------------------------
+     */
+    static {
+        AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                USER_HOME = System.getProperty("user.home") + "/.java/.userPrefs";//$NON-NLS-1$ //$NON-NLS-2$
+                SYSTEM_HOME = System.getProperty("java.home") + "/.systemPrefs";//$NON-NLS-1$//$NON-NLS-2$
+                return null;
+            }
+
+        });
+        userRoot = new FilePreferencesImpl(true);
+        systemRoot = new FilePreferencesImpl(false);
+    }
+
+    /*
+     * --------------------------------------------------------------
+     * Variables
+     * --------------------------------------------------------------
+     */
+
+    //file path for this preferences node
+    String path;
+
+    //internal cache for prefs key-value pair
+    private Properties prefs;
+
+    //file represents this preferences node
+    File prefsFile;
+
+    //parent dir for this preferences node
+    File dir;
+
+    //cache for removed prefs key-value pair
+    private Set removed = new HashSet();
+
+    //cache for updated prefs key-value pair
+    private Set updated = new HashSet();
+
+    /*
+     * --------------------------------------------------------------
+     * Constructors
+     * --------------------------------------------------------------
+     */
+    /*
+     * Construct a prefs using given parent and given name 
+     */
+    private FilePreferencesImpl(AbstractPreferences parent, String name) {
+        super(parent, name);
+        path = ((FilePreferencesImpl) parent).path + File.separator + name;
+        initPrefs();
+    }
+
+    private void initPrefs() {
+        dir = new File(path);
+        newNode = ((Boolean) AccessController
+                .doPrivileged(new PrivilegedAction() {
+                    public Object run() {
+                        return Boolean.valueOf(!dir.exists());
+                    }
+                })).booleanValue();
+        prefsFile = new File(path + File.separator + prefsFileName);
+        prefs = XMLParser.loadFilePrefs(prefsFile);
+    }
+
+    /*
+     * Construct root <code>FilePreferencesImpl</code> instance, construct 
+     * user root if userNode is true, system root otherwise
+     */
+    private FilePreferencesImpl(boolean userNode) {
+        super(null, ""); //$NON-NLS-1$
+        this.userNode = userNode;
+        path = userNode ? USER_HOME : SYSTEM_HOME;
+        initPrefs();
+    }
+
+    /*
+     * --------------------------------------------------------------
+     * Methods implement AbstractPreferences
+     * --------------------------------------------------------------
+     */
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#chilrenNamesSpi()
+     */
+    protected String[] childrenNamesSpi() throws BackingStoreException {
+        String[] names = (String[]) AccessController
+                .doPrivileged(new PrivilegedAction() {
+                    public Object run() {
+                        return dir.list(new FilenameFilter() {
+                            public boolean accept(File parent, String name) {
+                                return new File(path + File.separator + name)
+                                        .isDirectory(); //$NON-NLS-1$
+                            }
+                        });
+
+                    }
+                });
+        if (null == names) {// file is not a directory, exception case
+            throw new BackingStoreException(
+                    "Cannot get children names for " + toString() + "!"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        return names;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#childSpi()
+     */
+    protected AbstractPreferences childSpi(String name) {
+        FilePreferencesImpl child = new FilePreferencesImpl(this, name);
+        return child;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#flushSpi()
+     */
+    protected void flushSpi() throws BackingStoreException {
+        try {
+            //if removed, return
+            if(isRemoved()){
+                return;
+            }
+            // reload
+            Properties currentPrefs = XMLParser.loadFilePrefs(prefsFile);
+            // merge
+            Iterator it = removed.iterator();
+            while (it.hasNext()) {
+                currentPrefs.remove(it.next());
+            }
+            removed.clear();
+            it = updated.iterator();
+            while (it.hasNext()) {
+                Object key = it.next();
+                currentPrefs.put(key, prefs.get(key));
+            }
+            updated.clear();
+            // flush
+            prefs = currentPrefs;
+            XMLParser.flushFilePrefs(prefsFile, prefs);
+        } catch (Exception e) {
+            throw new BackingStoreException(e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#getSpi(java.lang.String)
+     */
+    protected String getSpi(String key) {
+        try {
+            if (null == prefs) {
+                prefs = XMLParser.loadFilePrefs(prefsFile);
+            }
+            return prefs.getProperty(key);
+        } catch (Exception e) {// if Exception happened, return null
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#keysSpi()
+     */
+    protected String[] keysSpi() throws BackingStoreException {
+        return (String[]) prefs.keySet().toArray(new String[0]);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#putSpi(java.lang.String,
+     *      java.lang.String)
+     */
+    protected void putSpi(String name, String value) {
+        prefs.setProperty(name, value);
+        updated.add(name);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#removeNodeSpi()
+     */
+    protected void removeNodeSpi() throws BackingStoreException {
+        boolean removeSucceed = ((Boolean) AccessController
+                .doPrivileged(new PrivilegedAction() {
+                    public Object run() {
+                        prefsFile.delete();
+                        return Boolean.valueOf(dir.delete());
+                    }
+                })).booleanValue();
+        if (!removeSucceed)
+            throw new BackingStoreException("Cannot remove " + toString() + "!"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#removeSpi(java.lang.String)
+     */
+    protected void removeSpi(String key) {
+        prefs.remove(key);
+        updated.remove(key);
+        removed.add(key);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.prefs.AbstractPreferences#syncSpi()
+     */
+    protected void syncSpi() throws BackingStoreException {
+        flushSpi();
+    }
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,86 @@
+/* Copyright 2005, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * An exception to indicate that the input XML file is not well-formed or 
+ * validating to the appropriate document type, which is specified by 
+ * <code>Preferences</code>. 
+ * <p>
+ * Please note that this class cannot be serialized actually, so relevant 
+ * serialization methods only throw <code>NotSerializableException</code>.</p>
+ * 
+ * @see Preferences
+ *
+ * @since 1.4
+ */
+public class InvalidPreferencesFormatException extends Exception {
+    
+	/**
+	 * Constructs a new <code>InvalidPreferencesFormatException</code> instance using an 
+	 * exception message.
+	 * 
+	 * @param s 	the exception message.
+	 */
+	public InvalidPreferencesFormatException (String s) {
+		super(s);
+	}
+
+	/**
+	 * Constructs a new <code>InvalidPreferencesFormatException</code> instance using a 
+	 * exception message and a nested <code>Throwable</code> instance.
+	 * 
+	 * @param s 	the exception message.
+	 * @param t		the nested <code>Throwable</code> instance.
+	 */
+	public InvalidPreferencesFormatException (String s, Throwable t) {
+		super(s,t);
+	}
+
+	/**
+	 * Constructs a new <code>InvalidPreferencesFormatException</code> instance using a
+	 * nested <code>Throwable</code> instance.
+	 *	
+	 * @param t		the nested <code>Throwable</code> instance.
+	 */
+	public InvalidPreferencesFormatException (Throwable t) {
+		super(t);
+	}
+	
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+	private void writeObject(ObjectOutputStream out) throws NotSerializableException{
+	    throw new NotSerializableException();	    
+	}
+	
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+	private void readObject(ObjectInputStream in) throws NotSerializableException{
+	    throw new NotSerializableException();	    
+	}	
+}
+
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,95 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.io.Serializable;
+import java.util.EventObject;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.NotSerializableException;
+import java.io.IOException;
+
+/**
+ * This is the event class to indicate one child of the preferences node has 
+ * been added or deleted.
+ * <p>
+ * Please note that this class cannot be serialized actually, so relevant 
+ * serialization methods only throw <code>NotSerializableException</code>.</p>
+ * 
+ * @see java.util.prefs.Preferences
+ * @see java.util.prefs.NodeChangeListener
+ * 
+ * @since 1.4
+ */
+public class NodeChangeEvent extends EventObject implements Serializable {
+	
+    static final long serialVersionUID = 8068949086596572957L;
+    
+    /**
+     * Construct a new <code>NodeChangeEvent</code> instance.
+     * 
+     * @param p		the <code>Preferences</code> instance that this event happened, 
+     * 				this object is considered as event's source.
+     * @param c		the child <code>Preferences</code> instance that was added 
+     * 				or deleted.
+     */
+	public NodeChangeEvent (Preferences p, Preferences c) {
+		super(p);
+		parent = p;
+		child = c;
+	}
+	
+	/**
+	 * Get the <code>Preferences</code> instance that this event happened.
+	 * 
+	 * @return		the <code>Preferences</code> instance that this event happened.
+	 */
+	public Preferences getParent() {
+		return parent;
+	}
+	
+	/**
+	 * Get the child <code>Preferences</code> node that was added or removed.
+	 * 
+	 * @return		the child <code>Preferences</code> node that was added or removed.
+	 */
+	public Preferences getChild() {
+		return child;
+	}
+	
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+	private void writeObject (ObjectOutputStream out) throws IOException {
+		throw new NotSerializableException();
+	}
+	
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+	private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException {
+		throw new NotSerializableException();
+	}
+
+	private Preferences parent, child;
+}
+
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeListener.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeListener.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeListener.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/NodeChangeListener.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,48 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.util.EventListener;
+import java.util.prefs.NodeChangeEvent;
+
+/**
+ * This interface is used to handle preferences node change event. Implmenetation 
+ * of this interface can be installed by <code>Preferences</code> instance.
+ * 
+ * @see Preferences
+ * @see NodeChangeEvent
+ * 
+ * @since 1.4
+ */
+public interface NodeChangeListener extends EventListener {
+	/**
+	 * This method gets called whenever a child is added to a node.
+	 * 
+	 * @param e Node change event.
+	 */
+	public void childAdded (NodeChangeEvent e);
+	
+	/**
+	 * This method gets called whenever a child is removed from a node.
+	 * 
+	 * @param e Node change event.
+	 */
+	public void childRemoved (NodeChangeEvent e);
+}
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,111 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.EventObject;
+
+/**
+ * This is the event class to indicate some preferences has been added, 
+ * deleted or updated.
+ * <p>
+ * Please note that this class cannot be serialized actually, so relevant 
+ * serialization methods only throw <code>NotSerializableException</code>.
+ * </p>
+ * 
+ * @see java.util.prefs.Preferences
+ * @see java.util.prefs.PreferenceChangeListener
+ * 
+ * @since 1.4
+ */
+public class PreferenceChangeEvent extends EventObject implements Serializable {
+
+    static final long serialVersionUID = 793724513368024975L;
+
+    /**
+     * Construct a new <code>PreferenceChangeEvent</code> instance.
+     * 
+     * @param p		the <code>Preferences</code> instance that this event happened, 
+     * 				this object is considered as event's source.
+     * @param k		the changed preference's key
+     * @param v		the new value of the changed preference, this value can be null, 
+     * 				which means the preference is removed.
+     */
+    public PreferenceChangeEvent(Preferences p, String k, String v) {
+        super(p);
+        node = p;
+        key = k;
+        value = v;
+    }
+
+    /**
+     * Get the changed preference's key.
+     * 
+     * @return the changed preference's key
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * Get the new value of the changed preference, or null if this preference 
+     * is removed.
+     * 
+     * @return the new value of the changed preference, or null if this preference 
+     * is removed.
+     */
+    public String getNewValue() {
+        return value;
+    }
+
+    /**
+     * Get the <code>Preferences</code> instance that this event happened.
+     * 
+     * @return the <code>Preferences</code> instance that this event happened.
+     */
+    public Preferences getNode() {
+        return node;
+    }
+
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        throw new NotSerializableException();
+    }
+
+    /*
+     * This method always throws a <code>NotSerializableException</code>, because 
+     * this object cannot be serialized,  
+     */
+    private void readObject(ObjectInputStream in) throws IOException{
+        throw new NotSerializableException();
+    }
+
+    private Preferences node;
+
+    private String key;
+
+    private String value;
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,44 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.util.EventListener;
+
+/**
+ * This interface is used to handle preferences change event. Implmenetation 
+ * of this interface can be installed by <code>Preferences</code> instance.
+ * 
+ * @see Preferences
+ * @see PreferenceChangeEvent
+ *
+ * 
+ * @since 1.4
+ */
+public interface PreferenceChangeListener extends EventListener {
+    
+    /**
+     * This method gets invoked whenener some preference is added, deleted or 
+     * updated.
+     * 
+     * @param pce 	the event instance which describes the changed Preferences 
+     * 				instance and preferences value.
+     */
+	void preferenceChange (PreferenceChangeEvent pce);
+}
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/Preferences.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/Preferences.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/Preferences.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/Preferences.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,846 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+
+
+/**
+ * <code>Preferences</code> instance represents one node in preferences tree,
+ * which provide a mechanisms to store and access configuration data in a
+ * hierarchical way. Two hierarchy tree is maintained, one for system
+ * preferences shared by all users, and the other for user preferences which is
+ * specific for each user. Preferences hierarchy tree and data is stored
+ * persistly in implementation-dependent backend, and user doesn't need to care
+ * about the details.
+ * <p>
+ * Every node has one name and one unique absolute path in a similiar way with
+ * directories in file system. The root node's name is "", and other nodes' name
+ * string cannot contains slash and cannot be empty. The root node's absolute
+ * path is "/", and other nodes' absolute path equals &lt;parent's absolute
+ * path&gt; + "/" + &lt;node's name&gt;. All absolute paths start with slash.
+ * Every node has one relative path to one of its ancestor. Relative path
+ * doesn't start with slash, and equals to absolute path when following after
+ * ancestor's absolute path and a slash.
+ * </p>
+ * <p>
+ * The modification to preferences data may be asynchronized, which means they
+ * may don't block and may returns immediately, implementation can feel free to
+ * the modifications to the backend in any time until the flush() or sync()
+ * method is invoked, these two methods force synchronized updates to backend.
+ * Please note that if JVM exit normally, the implementation must assure all
+ * modifications are persisted implicitly.
+ * </p>
+ * <p>
+ * User invoking methods that retrieve preferences must provide default value,
+ * default value is returned when preferences cannot be found or backend is
+ * unavailable. Some other methods will throw <code>BackingStoreException</code>
+ * when backend is unavailable.
+ * </p>
+ * <p>
+ * Preferences can be export to/import from xml files, the XML document must
+ * have the following DOCTYPE declaration:
+ * </p>
+ * <p>
+ * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
+ * </p>
+ * <p>
+ * This system URI is not really accessed by network, it is only a
+ * identification string. Visit the DTD location to see the actual format
+ * permitted.
+ * </p>
+ * <p>
+ * There has to be a concrete <code>PreferencesFactory</code> type for every
+ * concrete <code>Preferences</code> type developed. Every J2SE implementation
+ * must provide a default implementation for every supported platform, and the
+ * default implementation can be replaced in some way. This implementation uses
+ * system property java.util.prefs.PreferencesFactory to dictate the preferences
+ * implementation.
+ * </p>
+ * <p>
+ * Methods of this class is thread-safe. If multi JVMs using same backend
+ * concurrently, the backend won't be corrupted, but no other guarantees is
+ * made.
+ * </p>
+ * 
+ * @see PreferencesFactory
+ * 
+ * @since 1.4
+ */
+public abstract class Preferences {
+    
+    /**
+     * ---------------------------------------------------------
+     * Constants
+     * ---------------------------------------------------------
+     */
+	/**
+	 * Maximum size in characters of preferences key  
+	 */
+	public static final int MAX_KEY_LENGTH = 80;
+	
+	/**
+	 * Maximum size in characters of preferences name
+	 */
+	public static final int MAX_NAME_LENGTH = 80;
+	
+	/**
+	 * Maximum size in characters of preferences value
+	 */
+	public static final int MAX_VALUE_LENGTH = 8192;
+
+	//permission
+	private static final RuntimePermission perm = new RuntimePermission("preferences"); //$NON-NLS-1$
+	//factory used to get user/system prefs root
+	private static final PreferencesFactory factory;
+	
+    /**
+     * ---------------------------------------------------------
+     * Static init
+     * ---------------------------------------------------------
+     */		
+	static{
+	    String factoryClassName = (String)AccessController.doPrivileged(new PrivilegedAction(){
+            public Object run() {
+                return System.getProperty("java.util.prefs.PreferencesFactory"); //$NON-NLS-1$
+            }
+	    });
+	    try {
+	        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+	        if(loader == null){
+	            loader = ClassLoader.getSystemClassLoader();
+	        }
+	        Class factoryClass = loader.loadClass(factoryClassName);
+	        factory = (PreferencesFactory) factoryClass.newInstance();
+        } catch (Exception e) {
+            throw new InternalError("Cannot initiate PreferencesFactory: "+factoryClassName+". Caused by "+ e);  //$NON-NLS-1$//$NON-NLS-2$
+        }
+	    
+	}
+	
+    /**
+     * ---------------------------------------------------------
+     * Constructors
+     * ---------------------------------------------------------
+     */	
+	/**
+	 *	Default constructor, just for using by subclass.
+	 */
+	protected Preferences() {//empty constructor
+	}
+	
+    /**
+     * ---------------------------------------------------------
+     * Methods
+     * ---------------------------------------------------------
+     */	
+	/**
+	 * Get this preference node's absolute path string.
+	 * 
+	 * @return this preference node's absolute path string.
+	 */
+	public abstract String absolutePath();
+	
+	/**
+	 * Return names of all children of this node, or empty string if this node 
+	 * has no children. 
+	 * 
+	 * @return 		names of all children of this node
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract String[] childrenNames() throws BackingStoreException;
+	
+	/**
+	 * Remove all preferences of this node. 
+	 * 
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void clear() throws BackingStoreException;
+	
+	/**
+	 * Export all preferences of this node to the given output stream in XML 
+	 * document. 
+	 * <p>
+	 * This XML document has the following DOCTYPE declaration:
+	 * <pre>
+	 * &lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</pre>
+	 * And the utf-8 encoding will be used. Please note that this node is not 
+	 * thread-safe, which is an exception of this class. 
+	 * </p>
+	 * @param  ostream
+	 * 				the output stream to export the XML
+	 * @throws IOException
+	 * 				if export operation caused an <code>IOException</code>
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void exportNode (OutputStream ostream) throws IOException, BackingStoreException;
+	
+	/**
+	 * Export all preferences of this node and its all descendants to the given 
+	 * output stream in XML document. 
+	 * <p>
+	 * This XML document has the following DOCTYPE declaration:
+	 * <pre>
+	 * &lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</pre>	 * 
+	 * And the utf-8 encoding will be used. Please note that this node is not 
+	 * thread-safe, which is an exception of this class. 
+	 * </p>
+	 * @param  ostream
+	 * 				the output stream to export the XML
+	 * @throws IOException
+	 * 				if export operation caused an <code>IOException</code>
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void exportSubtree (OutputStream ostream) throws IOException, BackingStoreException;
+	
+	/**
+	 * Force the updates to this node and its descendants to the backing store. 
+	 * <p>
+	 * If this node has been removed, then the invocation of this method only 
+	 * flush this node without descendants.
+	 * </p> 
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 */
+	public abstract void flush() throws BackingStoreException;
+	
+	/**
+	 * Return the string value mapped to the given key, or default value if no 
+	 * value is mapped or backing store is unavailable.
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key or backing store unavailable 
+	 * @return 		the preference value mapped to the given key, or default value if 
+	 * 				no value is mapped or backing store unavailable 
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract String get (String key, String deflt);
+	
+	/**
+	 * Return the boolean value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid.
+	 * <p>
+	 * The valid value is string equals "true", which represents true, or "false", 
+	 * which represents false, case is ignored. 
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the boolean value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract boolean getBoolean (String key, boolean deflt);
+	
+	/**
+	 * Return the byte array value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid string.
+	 * <p>
+	 * The valid value string is Base64 encoded binary data. The Base64 encoding 
+	 * is as defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>, 
+	 * section 6.8.
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the byte array value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract byte[] getByteArray (String key, byte[] deflt);
+	
+	/**
+	 * Return the double value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid string.
+	 * <p>
+	 * The valid value string can be converted to double number by 
+	 * {@link Double#parseDouble(String) Double.parseDouble(String)}.
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the double value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract double getDouble (String key, double deflt);
+	
+	/**
+	 * Return the float value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid string.
+	 * <p>
+	 * The valid value string can be converted to float number by 
+	 * {@link Float#parseFloat(String) Float.parseFloat(String)}.
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the float value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract float getFloat (String key, float deflt);
+	
+	/**
+	 * Return the float value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid string.
+	 * <p>
+	 * The valid value string can be converted to integer by 
+	 * {@link Integer#parseInt(String) Integer.parseInt(String)}.
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the integer value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract int getInt (String key, int deflt);
+	
+	/**
+	 * Return the long value mapped to the given key, or default value if no 
+	 * value is mapped, backing store is unavailable, or the value is invalid string.
+	 * <p>
+	 * The valid value string can be converted to long integer by 
+	 * {@link Long#parseLong(String) Long.parseLong(String)}.
+	 * </p>  
+	 * <p>
+	 * Some implementations may store default values in backing stores. In this case, 
+	 * if there is no value mapped to the given key, the stored default value is 
+	 * returned.
+	 * </p>
+	 * 
+	 * @param key	the preference key
+	 * @param deflt	the default value, which will be returned if no value is 
+	 * 				mapped to the given key, backing store unavailable or value 
+	 * 				is invalid 
+	 * @return 		the long value mapped to the given key, or default value if 
+	 * 				no value is mapped, backing store unavailable or value is invalid
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws NullPointerException
+	 * 				if parameter key is null 
+	 */
+	public abstract long getLong (String key, long deflt);
+	
+	/**
+	 * Import all preferences from the given input stream in XML document. 
+	 * <p>
+	 * This XML document has the following DOCTYPE declaration:
+	 * <pre>
+	 * &lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</pre>	 * 
+	 * Please note that this node is not thread-safe, which is an exception of 
+	 * this class. 
+	 * </p>
+	 * 
+	 * @param istream
+	 * 				the given input stream to read data
+	 * @throws InvalidPreferencesFormatException
+	 * 				if the data read from given input stream is not valid XML 
+	 * 				document
+	 * @throws IOException
+	 * 				if import operation caused an <code>IOException</code>
+	 * @throws SecurityException
+	 * 				if <code>RuntimePermission("preferences")</code> is denied 
+	 * 				by a <code>SecurityManager</code>
+	 */
+	public static void importPreferences (InputStream istream) throws InvalidPreferencesFormatException, IOException {
+	    checkSecurity();
+	    if(null == istream){
+	        throw new MalformedURLException("Inputstream cannot be null!");
+	    }
+	    XMLParser.importPrefs(istream);
+	}
+	
+	/**
+	 * Return true if this is a user preferences, false if this is a system 
+	 * perferences
+	 * 
+	 * @return 		true if this is a user preferences, false if this is a 
+	 * 				system perferences
+	 */
+	public abstract boolean isUserNode();
+	
+	/**
+	 * Return all preferences keys stored in this node, or empty array if no 
+	 * key is found.
+	 * 
+	 * @return 		all preferences keys in this node
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract String[] keys() throws BackingStoreException;
+	
+	/**
+	 * Return name of this node.
+	 * 
+	 * @return 		the name of this node
+	 */
+	public abstract String name();
+	
+	/**
+	 * Return the preferences node with the given path name. The path name can 
+	 * be relative or absolute. The dictated preferences and its ancestors will 
+	 * be created if they do not exist.
+	 * <p>
+	 * The path is treated as relative to this node if it doesn't start with 
+	 * slash, or as absolute otherwise.</p>  
+	 *  
+	 * @param path	the path name of dictated preferences
+	 * @return 		the dictated preferences node
+	 * @throws IllegalStateException
+	 * 				if this node has been removed.
+	 * @throws IllegalArgumentException
+	 * 				if the path name is invalid.
+	 * @throws NullPointerException
+	 * 				if given path is null.
+	 */
+	public abstract Preferences node (String path);
+	
+	/**
+	 * Return the preferences node with the given path name. The path is treated 
+	 * as relative to this node if it doesn't start with slash, or as absolute 
+	 * otherwise.
+	 * <p>
+	 * Please note that if this node has been removed, invocation of this node 
+	 * will throw <code>IllegalStateException</code> except the given path is 
+	 * empty string, which will return false.
+	 * </p>
+	 * 
+	 * @param path	the path name of dictated preferences
+	 * @return 		true if the dictated preferences node exists
+	 * @throws IllegalStateException
+	 * 				if this node has been removed and the path is not empty string.
+	 * @throws IllegalArgumentException
+	 * 				if the path name is invalid.
+	 * @throws NullPointerException
+	 * 				if given path is null.
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 */
+	public abstract boolean nodeExists (String path) throws BackingStoreException;
+	
+	/**
+	 * Return the parent preferences node of this node, or null if this node is root.
+	 * 
+	 * @return the parent preferences node of this node.
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract Preferences parent();
+	
+	/**
+	 * Add new preferences to this node using given key and value, or update 
+	 * value if preferences with given key has already existed.
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key or value is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>, or the value's length is bigger 
+	 * 				than <code>MAX_VALUE_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void put (String key, String value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putBoolean (String key, boolean value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * <p>
+	 * The string form of value is the Base64 encoded binary data of the given 
+	 * byte array. The Base64 encoding is as defined in 
+	 * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>, section 6.8.</p>
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key or value is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code> or value's length is bigger than  
+	 * 				three quaters of <code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putByteArray (String key, byte[] value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * <p>
+	 * The string form of given value is the result of invoking 
+	 * {@link Double#toString(double) Double.toString(double)}</p>
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putDouble (String key, double value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * <p>
+	 * The string form of given value is the result of invoking 
+	 * {@link Float#toString(float) Float.toString(float)}</p>
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putFloat (String key, float value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * <p>
+	 * The string form of given value is the result of invoking 
+	 * {@link Integer#toString(int) Integer.toString(int)}</p>
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putInt (String key, int value);
+	
+	/**
+	 * Add new preferences to this node using given key and string form of given 
+	 * value, or update value if preferences with given key has already existed. 
+	 * <p>
+	 * The string form of given value is the result of invoking 
+	 * {@link Long#toString(long) Long.toString(long)}</p>
+	 * 
+	 * @param key	the preferences key to be added or be updated 
+	 * @param value	the preferences value for the given key
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalArgumentException
+	 * 				if the given key's length is bigger than 
+	 * 				<code>MAX_KEY_LENGTH</code>
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void putLong (String key, long value);
+
+	/**
+	 * Remove the preferences mapped to the given key from this node.
+	 * 
+	 * @param key	the given preferences key to removed 
+	 * @throws NullPointerException
+	 * 				if the given key is null
+	 * @throws IllegalStateException
+	 * 			if this node has been removed	
+	 */
+	public abstract void remove (String key);
+	
+	/**
+	 * Remove this preferences node and its all descendents. The removal maybe
+	 * won't be persisted until the <code>flush()</code> method is invoked. 
+	 * 
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure 
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 * @throws UnsupportedOperationException
+	 * 				if this is a root node
+	 */
+	public abstract void removeNode() throws BackingStoreException;
+	
+	/**
+	 * Register an <code>NodeChangeListener</code> instance for this node, which 
+	 * will receive <code>NodeChangeEvent</code>. <code>NodeChangeEvent</code> will 
+	 * be produced when direct child node is added to or removed from this node. 
+	 * 
+	 * @param ncl	the given listener to be registered
+	 * @throws NullPointerException
+	 * 				if the given listener is null
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void addNodeChangeListener (NodeChangeListener ncl);
+	
+	/**
+	 * Register an <code>PreferenceChangeListener</code> instance for this node, which 
+	 * will receive <code>PreferenceChangeEvent</code>. <code>PreferenceChangeEvent</code> will 
+	 * be produced when preference is added to, removed from or updated for this node. 
+	 * 
+	 * @param pcl	the given listener to be registered
+	 * @throws NullPointerException
+	 * 				if the given listener is null
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void addPreferenceChangeListener (PreferenceChangeListener pcl);
+	
+	/**
+	 * Remove the given <code>NodeChangeListener</code> instance from this node. 
+	 * 
+	 * @param ncl	the given listener to be removed
+	 * @throws IllegalArgumentException
+	 * 				if the given listener 
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void removeNodeChangeListener (NodeChangeListener ncl);
+	
+	/**
+	 * Remove the given <code>PreferenceChangeListener</code> instance from this node. 
+	 * 
+	 * @param pcl	the given listener to be removed
+	 * @throws IllegalArgumentException
+	 * 				if the given listener 
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void removePreferenceChangeListener (PreferenceChangeListener pcl);
+	
+	/**
+	 * Synchronize this prefernces node and its descendants' data with the back 
+	 * end prefernces store. The changes of back end should be reflect by this 
+	 * node and its descendants, meanwhile, the changes of this node and descendants 
+	 * should be persisted.
+	 * 
+	 * @throws BackingStoreException
+	 * 				if backing store is unavailable or causes operation failure
+	 * @throws IllegalStateException
+	 * 				if this node has been removed
+	 */
+	public abstract void sync() throws BackingStoreException;
+	
+    /**
+     * Return the system preference node for the package of given class. The 
+     * absolute path of the returned node is one slash followed by the given 
+     * class's full package name with replacing each period ('.') with slash.
+     * For example, the preference's associated with class <code>Object<code> 
+     * has absolute path like "/java/lang". As a special case, the unnamed 
+     * package is associated with preference node "/<unnamed>". 
+     *  
+	 * This method will create node and its ancestors if needed, and the new 
+	 * created nodes maybe won't be persisted until the <code>flush()</code> 
+	 * is invoked.
+	 * 
+	 * @param c		the given class 
+	 * @return 		the system preference node for the package of given class. 
+	 * @throws NullPointerException
+	 * 				if the given class is null
+	 * @throws SecurityException
+	 * 				if <code>RuntimePermission("preferences")</code> is denied 
+	 * 				by a <code>SecurityManager</code>
+	 */
+	public static Preferences systemNodeForPackage (Class c) {
+	    checkSecurity();
+		return factory.systemRoot().node(getNodeName(c));
+	}
+	
+	/**
+	 * Return the root node for system preference hierarchy.
+	 * 
+	 * @return 		the root node for system preference hierarchy
+	 * @throws SecurityException
+	 * 				if <code>RuntimePermission("preferences")</code> is denied 
+	 * 				by a <code>SecurityManager</code>
+	 */
+	public static Preferences systemRoot() {
+	    checkSecurity();
+	    return factory.systemRoot();
+	}
+	
+	//check the RuntimePermission("preferences")
+    private static void checkSecurity() {
+        SecurityManager manager = System.getSecurityManager();
+        if(null != manager){
+            manager.checkPermission(perm);
+        }
+        
+    }
+
+    /**
+     * Return the user preference node for the package of given class. The 
+     * absolute path of the returned node is one slash followed by the given 
+     * class's full package name with replacing each period ('.') with slash.
+     * For example, the preference's associated with class <code>Object<code> 
+     * has absolute path like "/java/lang". As a special case, the unnamed 
+     * package is associated with preference node "/<unnamed>". 
+     *  
+	 * This method will create node and its ancestors if needed, and the new 
+	 * created nodes maybe won't be persisted until the <code>flush()</code> 
+	 * is invoked.
+	 * 
+	 * @param c	the given class 
+	 * @return 		the user preference node for the package of given class. 
+	 * @throws NullPointerException
+	 * 	 				if the given class is null
+	 * @throws SecurityException
+	 * 				if <code>RuntimePermission("preferences")</code> is denied 
+	 * 				by a <code>SecurityManager</code>
+	 */
+	public static Preferences userNodeForPackage (Class c) {
+	    checkSecurity();
+		return factory.userRoot().node(getNodeName(c));
+	}
+	
+	//parse node's absolute path from class instance
+	private static String getNodeName(Class c){
+	    Package p = c.getPackage();
+	    if(null == p){
+	        return "/<unnamed>"; //$NON-NLS-1$
+	    }
+	    return "/"+p.getName().replace('.', '/'); //$NON-NLS-1$
+	}
+
+	/**
+	 * Return the root node for user preference hierarchy.
+	 * 
+	 * @return 		the root node for user preference hierarchy
+	 * @throws SecurityException
+	 * 				if <code>RuntimePermission("preferences")</code> is denied 
+	 * 				by a <code>SecurityManager</code>
+	 */
+	public static Preferences userRoot() {
+	    checkSecurity();
+	    return factory.userRoot();
+	}
+	
+	/**
+	 * Return a string description of this node. The format is "User/System 
+	 * Preference Node: " followed by this node's absolute path.
+	 * 
+	 * @return a string description of this node
+	 * 
+	 */
+	public abstract String toString();
+}
+
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferencesFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferencesFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferencesFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/PreferencesFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,47 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+/**
+ * This interfaceis used by {@link java.util.prefs.Preferences Preferences} class 
+ * as factory class to create Preferences instance. This interface can be implemented 
+ * and installed to replace the default preferences implementation.
+ * 
+ * @see java.util.prefs.Preferences
+ * 
+ * @since 1.4
+ */
+public interface PreferencesFactory {
+	/**
+	 * Returns the root of the preferences hierarchy for the calling user
+	 * context.
+	 * 
+	 * @return The user root preferences node.
+	 */
+	Preferences userRoot();
+	
+	/**
+	 * Returns the root of the system preferences hierarchy.
+	 * 
+	 * @return The root of the system preferences hierarchy.
+	 */
+	Preferences systemRoot();
+}
+
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesFactoryImpl.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesFactoryImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesFactoryImpl.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,55 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+import java.util.prefs.Preferences;
+import java.util.prefs.PreferencesFactory;
+
+/*
+ * Default implementation of <code>PreferencesFactory</code> for windows 
+ * platform, using windows Registry as back end.
+ * 
+ * @since 1.4
+ */
+class RegistryPreferencesFactoryImpl implements PreferencesFactory {
+    
+    /*
+     * Default constructor
+     */
+    public RegistryPreferencesFactoryImpl() {
+    	super();
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.prefs.PreferencesFactory#userRoot()
+     */
+    public Preferences userRoot() {
+        return RegistryPreferencesImpl.USER_ROOT;
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.prefs.PreferencesFactory#systemRoot()
+     */
+    public Preferences systemRoot() {
+        return RegistryPreferencesImpl.SYSTEM_ROOT;
+    }
+
+}
+
+
+
+ 

Added: incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesImpl.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/prefs/src/main/java/java/util/prefs/RegistryPreferencesImpl.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,244 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util.prefs;
+
+/*
+ * Default implementation of <code>AbstractPreferences</code> for windows platform,
+ * using windows registry as back end. 
+ * 
+ * @since 1.4
+ */
+class RegistryPreferencesImpl extends AbstractPreferences {
+    
+    static {
+		System.loadLibrary("hyprefs");
+	}
+
+    /*
+	 * -------------------------------------------------------------- Constants
+	 * --------------------------------------------------------------
+	 */
+    //registry path for root preferences 
+    private final static String ROOT_PATH = "SOFTWARE\\JavaSoft\\Prefs"; //$NON-NLS-1$
+
+    //index for returned error code
+    private final static int ERROR_CODE = 0;
+
+    //error code for registry access    
+    final static int RETURN_SUCCESS = 0;
+
+    final static int RETURN_FILE_NOT_FOUND = 1;
+
+    final static int RETURN_ACCESS_DENIED = 2;
+
+    final static int RETURN_UNKNOWN_ERROR = 3;
+
+    //user root preferences
+    final static Preferences USER_ROOT = new RegistryPreferencesImpl(true);
+
+    //system root preferences
+    final static Preferences SYSTEM_ROOT = new RegistryPreferencesImpl(false);
+
+    /*
+     * --------------------------------------------------------------
+     * Variables
+     * --------------------------------------------------------------
+     */
+    //registry path for this preferences, default value is root's path
+    private byte[] path = ROOT_PATH.getBytes();
+
+    /*
+     * --------------------------------------------------------------
+     * Constructors
+     * --------------------------------------------------------------
+     */
+    /*
+     * Construct <code>RegistryPreferencesImpl</code> instance using given parent 
+     * and given name 
+     */
+    public RegistryPreferencesImpl(AbstractPreferences parent, String name) {
+        super(parent, name);
+        this.userNode = parent.isUserNode();
+        path = (ROOT_PATH + encodeWindowsStr(absolutePath())).getBytes();
+    }
+
+    /*
+     * Construct root <code>RegistryPreferencesImpl</code> instance, construct 
+     * user root if userNode is true, system root otherwise
+     */
+    public RegistryPreferencesImpl(boolean userNode) {
+        super(null, ""); //$NON-NLS-1$
+        this.userNode = userNode;
+    }
+
+    /*
+     * --------------------------------------------------------------
+     * Methods implement AbstractPreferences
+     * --------------------------------------------------------------
+     */
+    protected String[] childrenNamesSpi() throws BackingStoreException {
+        int[] error = new int[1];
+        byte[][] names = getChildNames(path, userNode, error);
+        if (error[ERROR_CODE] != RETURN_SUCCESS) {
+            throw new BackingStoreException("Enumerate child nodes error!"); //$NON-NLS-1$
+        }
+        String[] result = new String[names.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = decodeWindowsStr(new String(names[i]));
+        }
+        return result;
+    }
+
+    protected AbstractPreferences childSpi(String name) {
+        int[] error = new int[1];
+        RegistryPreferencesImpl result = new RegistryPreferencesImpl(this, name);
+        //FIXME: is it right thing to set newNode here?
+        result.newNode = getNode(path, encodeWindowsStr(name).getBytes(), result.userNode, error);
+        if (error[ERROR_CODE] == RETURN_ACCESS_DENIED) {
+            throw new SecurityException();
+        }
+        return result;
+    }
+
+    protected void flushSpi() throws BackingStoreException {
+        int[] error = new int[1];
+        flushPrefs(path, userNode, error);
+        if (error[ERROR_CODE] != RETURN_SUCCESS) {
+            throw new BackingStoreException("Flush error!"); //$NON-NLS-1$
+        }
+    }
+
+    protected String getSpi(String key) {
+        int[] error = new int[1];
+        byte[] result = getValue(path, encodeWindowsStr(key).getBytes(), userNode, error);
+        if (error[ERROR_CODE] != 0) {
+            return null;
+        }
+        return new String(result);
+    }
+
+    protected String[] keysSpi() throws BackingStoreException {
+        int[] errorCode = new int[1];
+        byte[][] keys = keys(path, userNode, errorCode);
+        if (errorCode[ERROR_CODE] != RETURN_SUCCESS) {
+            throw new BackingStoreException("Enumerate keys error!"); //$NON-NLS-1$
+        }
+        String[] result = new String[keys.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = decodeWindowsStr(new String(keys[i]));
+        }
+        return result;
+    }
+
+    protected void putSpi(String name, String value) {
+        int[] errorCode = new int[1];
+        putValue(path, encodeWindowsStr(name).getBytes(), value.getBytes(), userNode, errorCode);
+        if (errorCode[ERROR_CODE] == RETURN_ACCESS_DENIED) {
+            throw new SecurityException("Access denied!"); //$NON-NLS-1$
+        }
+    }
+
+    protected void removeNodeSpi() throws BackingStoreException {
+        int[] error = new int[1];
+        removeNode(((RegistryPreferencesImpl) parent()).path,
+                encodeWindowsStr(name()).getBytes(), userNode, error);
+        if (error[ERROR_CODE] != RETURN_SUCCESS) {
+            throw new BackingStoreException("Remove node error!"); //$NON-NLS-1$
+        }
+    }
+
+    protected void removeSpi(String key) {
+        int[] errorCode = new int[1];
+        removeKey(path, encodeWindowsStr(key).getBytes(), userNode, errorCode);
+        if (errorCode[ERROR_CODE] == RETURN_ACCESS_DENIED) {
+            throw new SecurityException("Access denied!"); //$NON-NLS-1$
+        }
+    }
+
+    protected void syncSpi() throws BackingStoreException {
+        flushSpi();
+    }
+
+    //handle the lower/upper case pitfall
+    private static String encodeWindowsStr(String str){
+        char[] chars = str.toCharArray();
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < chars.length; i++) {
+            char c = chars[i];
+            if(c == '/'){
+                buffer.append("\\"); //$NON-NLS-1$
+            }else if(c == '\\'){
+                buffer.append("//"); //$NON-NLS-1$
+            }else if((c >= 'A') && (c <= 'Z')){
+                buffer.append('/').append(c);
+            }else{
+                buffer.append(c);
+            }
+        }
+        return buffer.toString();
+    }
+    private static String decodeWindowsStr(String str){
+        StringBuffer buffer = new StringBuffer();
+        char[] chars = str.toCharArray();
+        for (int i = 0; i < chars.length; i++) {
+            char c= chars[i];
+            if(c == '\\'){
+                buffer.append('/');
+            }else if(c == '/'){
+                if((c = chars[++i]) == '/'){
+                    buffer.append('\\');
+                }else{
+                    buffer.append(c);
+                }
+            }else{
+                buffer.append(c);
+            }
+        }
+        return buffer.toString();
+    }
+    
+    /*
+     * --------------------------------------------------------------
+     * Native methods declaration
+     * --------------------------------------------------------------
+     */
+    private native byte[] getValue(byte[] registryPath, byte[] key,
+            boolean isUserNode, int[] errorCode);
+
+    private native void putValue(byte[] registryPath, byte[] key, byte[] value,
+            boolean isUserNode, int[] errorCode);
+
+    private native void removeKey(byte[] registryPath, byte[] key,
+            boolean isUserNode, int[] errorCode);
+
+    private native byte[][] keys(byte[] registryPath, boolean isUserNode,
+            int[] errorCode);
+
+    private native void removeNode(byte[] registryPath, byte[] name,
+            boolean isUserNode, int[] errorCode);
+
+    private native boolean getNode(byte[] registryPath, byte[] name,
+            boolean isUserNode, int[] errorCode);
+
+    private native byte[][] getChildNames(byte[] registryPath,
+            boolean isUserNode, int[] errorCode);
+
+    private native void flushPrefs(byte[] registryPath, boolean isUserNode,
+            int[] errorCode) throws SecurityException;
+}
+
+