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 <parent's absolute
+ * path> + "/" + <node's name>. 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>
+ * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"></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>
+ * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"></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>
+ * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"></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;
+}
+
+