8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,280 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.util.Objects;
class MacOSXPreferences extends AbstractPreferences {
// fixme need security checks?
// CF preferences file name for Java nodes with short names
// This value is also in MacOSXPreferencesFile.c
private static final String defaultAppName = "com.apple.java.util.prefs";
// true if this node is a child of userRoot or is userRoot
private final boolean isUser;
// CF's storage location for this node and its keys
private final MacOSXPreferencesFile file;
// absolutePath() + "/"
private final String path;
// User root and system root nodes
private static volatile MacOSXPreferences userRoot;
private static volatile MacOSXPreferences systemRoot;
// Returns user root node, creating it if necessary.
// Called by MacOSXPreferencesFactory
static Preferences getUserRoot() {
MacOSXPreferences root = userRoot;
if (root == null) {
synchronized (MacOSXPreferences.class) {
root = userRoot;
if (root == null) {
userRoot = root = new MacOSXPreferences(true);
}
}
}
return root;
}
// Returns system root node, creating it if necessary.
// Called by MacOSXPreferencesFactory
static Preferences getSystemRoot() {
MacOSXPreferences root = systemRoot;
if (root == null) {
synchronized (MacOSXPreferences.class) {
root = systemRoot;
if (root == null) {
systemRoot = root = new MacOSXPreferences(false);
}
}
}
return root;
}
// Create a new root node. Called by getUserRoot() and getSystemRoot()
// Synchronization is provided by the caller.
private MacOSXPreferences(boolean newIsUser) {
this(null, "", false, true, newIsUser);
}
// Create a new non-root node with the given parent.
// Called by childSpi().
private MacOSXPreferences(MacOSXPreferences parent, String name) {
this(parent, name, false, false, false);
}
private MacOSXPreferences(MacOSXPreferences parent, String name,
boolean isNew)
{
this(parent, name, isNew, false, false);
}
private MacOSXPreferences(MacOSXPreferences parent, String name,
boolean isNew, boolean isRoot, boolean isUser)
{
super(parent, name);
if (isRoot)
this.isUser = isUser;
else
this.isUser = isUserNode();
path = isRoot ? absolutePath() : absolutePath() + "/";
file = cfFileForNode(this.isUser);
if (isNew)
newNode = isNew;
else
newNode = file.addNode(path);
}
// Create and return the MacOSXPreferencesFile for this node.
// Does not write anything to the file.
private MacOSXPreferencesFile cfFileForNode(boolean isUser)
{
String name = path;
// /one/two/three/four/five/
// The fourth slash is the end of the first three components.
// If there is no fourth slash, the name has fewer than 3 components
int pos = -1;
for (int i = 0; i < 4; i++) {
pos = name.indexOf('/', pos+1);
if (pos == -1) break;
}
if (pos == -1) {
// fewer than three components - use default name
name = defaultAppName;
} else {
// truncate to three components, no leading or trailing '/'
// replace '/' with '.' to make filesystem happy
// convert to all lowercase to survive on HFS+
name = name.substring(1, pos);
name = name.replace('/', '.');
name = name.toLowerCase();
}
return MacOSXPreferencesFile.getFile(name, isUser);
}
// AbstractPreferences implementation
@Override
protected void putSpi(String key, String value)
{
file.addKeyToNode(path, key, value);
}
// AbstractPreferences implementation
@Override
protected String getSpi(String key)
{
return file.getKeyFromNode(path, key);
}
// AbstractPreferences implementation
@Override
protected void removeSpi(String key)
{
Objects.requireNonNull(key, "Specified key cannot be null");
file.removeKeyFromNode(path, key);
}
// AbstractPreferences implementation
@Override
protected void removeNodeSpi()
throws BackingStoreException
{
// Disallow flush or sync between these two operations
// (they may be manipulating two different files)
synchronized(MacOSXPreferencesFile.class) {
((MacOSXPreferences)parent()).removeChild(name());
file.removeNode(path);
}
}
// Erase knowledge about a child of this node. Called by removeNodeSpi.
private void removeChild(String child)
{
file.removeChildFromNode(path, child);
}
// AbstractPreferences implementation
@Override
protected String[] childrenNamesSpi()
throws BackingStoreException
{
String[] result = file.getChildrenForNode(path);
if (result == null) throw new BackingStoreException("Couldn't get list of children for node '" + path + "'");
return result;
}
// AbstractPreferences implementation
@Override
protected String[] keysSpi()
throws BackingStoreException
{
String[] result = file.getKeysForNode(path);
if (result == null) throw new BackingStoreException("Couldn't get list of keys for node '" + path + "'");
return result;
}
// AbstractPreferences implementation
@Override
protected AbstractPreferences childSpi(String name)
{
// Add to parent's child list here and disallow sync
// because parent and child might be in different files.
synchronized(MacOSXPreferencesFile.class) {
boolean isNew = file.addChildToNode(path, name);
return new MacOSXPreferences(this, name, isNew);
}
}
// AbstractPreferences override
@Override
public void flush()
throws BackingStoreException
{
// Flush should *not* check for removal, unlike sync, but should
// prevent simultaneous removal.
synchronized(lock) {
if (isUser) {
if (!MacOSXPreferencesFile.flushUser()) {
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
}
} else {
if (!MacOSXPreferencesFile.flushWorld()) {
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
}
}
}
}
// AbstractPreferences implementation
@Override
protected void flushSpi()
throws BackingStoreException
{
// nothing here - overridden flush() doesn't call this
}
// AbstractPreferences override
@Override
public void sync()
throws BackingStoreException
{
synchronized(lock) {
if (isRemoved())
throw new IllegalStateException("Node has been removed");
// fixme! overkill
if (isUser) {
if (!MacOSXPreferencesFile.syncUser()) {
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
}
} else {
if (!MacOSXPreferencesFile.syncWorld()) {
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
}
}
}
}
// AbstractPreferences implementation
@Override
protected void syncSpi()
throws BackingStoreException
{
// nothing here - overridden sync() doesn't call this
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
class MacOSXPreferencesFactory implements PreferencesFactory {
@Override
public Preferences userRoot() {
return MacOSXPreferences.getUserRoot();
}
@Override
public Preferences systemRoot() {
return MacOSXPreferences.getSystemRoot();
}
}

View file

@ -0,0 +1,487 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.lang.ref.WeakReference;
/*
MacOSXPreferencesFile synchronization:
Everything is synchronized on MacOSXPreferencesFile.class. This prevents:
* simultaneous updates to cachedFiles or changedFiles
* simultaneous creation of two objects for the same name+user+host triplet
* simultaneous modifications to the same file
* modifications during syncWorld/flushWorld
* (in MacOSXPreferences.removeNodeSpi()) modification or sync during
multi-step node removal process
... among other things.
*/
/*
Timers. There are two timers that control synchronization of prefs data to
and from disk.
* Sync timer periodically calls syncWorld() to force external disk changes
(e.g. from another VM) into the memory cache. The sync timer runs even
if there are no outstanding local changes. The sync timer syncs all live
MacOSXPreferencesFile objects (the cachedFiles list).
The sync timer period is controlled by the java.util.prefs.syncInterval
property (same as FileSystemPreferences). By default there is *no*
sync timer (unlike FileSystemPreferences); it is only enabled if the
syncInterval property is set. The minimum interval is 5 seconds.
* Flush timer calls flushWorld() to force local changes to disk.
The flush timer is scheduled to fire some time after each pref change,
unless it's already scheduled to fire before that. syncWorld and
flushWorld will cancel any outstanding flush timer as unnecessary.
The flush timer flushes all changed files (the changedFiles list).
The time between pref write and flush timer call is controlled by the
java.util.prefs.flushDelay property (unlike FileSystemPreferences).
The default is 60 seconds and the minimum is 5 seconds.
The flush timer's behavior is required by the Java Preferences spec
("changes will eventually propagate to the persistent backing store with
an implementation-dependent delay"). The sync timer is not required by
the spec (multiple VMs are only required to not corrupt the prefs), but
the periodic sync is implemented by FileSystemPreferences and may be
useful to some programs. The sync timer is disabled by default because
it's expensive and is usually not necessary.
*/
class MacOSXPreferencesFile {
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("prefs");
return null;
}
});
}
private class FlushTask extends TimerTask {
public void run() {
MacOSXPreferencesFile.flushWorld();
}
}
private class SyncTask extends TimerTask {
public void run() {
MacOSXPreferencesFile.syncWorld();
}
}
// Maps string -> weak reference to MacOSXPreferencesFile
private static HashMap<String, WeakReference<MacOSXPreferencesFile>>
cachedFiles;
// Files that may have unflushed changes
private static HashSet<MacOSXPreferencesFile> changedFiles;
// Timer and pending sync and flush tasks (which are both scheduled
// on the same timer)
private static Timer timer = null;
private static FlushTask flushTimerTask = null;
private static long flushDelay = -1; // in seconds (min 5, default 60)
private static long syncInterval = -1; // (min 5, default negative == off)
private String appName;
private long user;
private long host;
String name() { return appName; }
long user() { return user; }
long host() { return host; }
// private constructor - use factory method getFile() instead
private MacOSXPreferencesFile(String newName, long newUser, long newHost)
{
appName = newName;
user = newUser;
host = newHost;
}
// Factory method
// Always returns the same object for the given name+user+host
static synchronized MacOSXPreferencesFile
getFile(String newName, boolean isUser)
{
MacOSXPreferencesFile result = null;
if (cachedFiles == null)
cachedFiles = new HashMap<>();
String hashkey =
newName + String.valueOf(isUser);
WeakReference<MacOSXPreferencesFile> hashvalue = cachedFiles.get(hashkey);
if (hashvalue != null) {
result = hashvalue.get();
}
if (result == null) {
// Java user node == CF current user, any host
// Java system node == CF any user, current host
result = new MacOSXPreferencesFile(newName,
isUser ? cfCurrentUser : cfAnyUser,
isUser ? cfAnyHost : cfCurrentHost);
cachedFiles.put(hashkey, new WeakReference<MacOSXPreferencesFile>(result));
}
// Don't schedule this file for flushing until some nodes or
// keys are added to it.
// Do set up the sync timer if requested; sync timer affects reads
// as well as writes.
initSyncTimerIfNeeded();
return result;
}
// Write all prefs changes to disk and clear all cached prefs values
// (so the next read will read from disk).
static synchronized boolean syncWorld()
{
boolean ok = true;
if (cachedFiles != null && !cachedFiles.isEmpty()) {
Iterator<WeakReference<MacOSXPreferencesFile>> iter =
cachedFiles.values().iterator();
while (iter.hasNext()) {
WeakReference<MacOSXPreferencesFile> ref = iter.next();
MacOSXPreferencesFile f = ref.get();
if (f != null) {
if (!f.synchronize()) ok = false;
} else {
iter.remove();
}
}
}
// Kill any pending flush
if (flushTimerTask != null) {
flushTimerTask.cancel();
flushTimerTask = null;
}
// Clear changed file list. The changed files were guaranteed to
// have been in the cached file list (because there was a strong
// reference from changedFiles.
if (changedFiles != null) changedFiles.clear();
return ok;
}
// Sync only current user preferences
static synchronized boolean syncUser() {
boolean ok = true;
if (cachedFiles != null && !cachedFiles.isEmpty()) {
Iterator<WeakReference<MacOSXPreferencesFile>> iter =
cachedFiles.values().iterator();
while (iter.hasNext()) {
WeakReference<MacOSXPreferencesFile> ref = iter.next();
MacOSXPreferencesFile f = ref.get();
if (f != null && f.user == cfCurrentUser) {
if (!f.synchronize()) {
ok = false;
}
} else {
iter.remove();
}
}
}
// Remove synchronized file from changed file list. The changed files were
// guaranteed to have been in the cached file list (because there was a strong
// reference from changedFiles.
if (changedFiles != null) {
Iterator<MacOSXPreferencesFile> iterChanged = changedFiles.iterator();
while (iterChanged.hasNext()) {
MacOSXPreferencesFile f = iterChanged.next();
if (f != null && f.user == cfCurrentUser)
iterChanged.remove();
}
}
return ok;
}
//Flush only current user preferences
static synchronized boolean flushUser() {
boolean ok = true;
if (changedFiles != null && !changedFiles.isEmpty()) {
Iterator<MacOSXPreferencesFile> iterator = changedFiles.iterator();
while(iterator.hasNext()) {
MacOSXPreferencesFile f = iterator.next();
if (f.user == cfCurrentUser) {
if (!f.synchronize())
ok = false;
else
iterator.remove();
}
}
}
return ok;
}
// Write all prefs changes to disk, but do not clear all cached prefs
// values. Also kills any scheduled flush task.
// There's no CFPreferencesFlush() (<rdar://problem/3049129>), so lots of cached prefs
// are cleared anyway.
static synchronized boolean flushWorld()
{
boolean ok = true;
if (changedFiles != null && !changedFiles.isEmpty()) {
for (MacOSXPreferencesFile f : changedFiles) {
if (!f.synchronize())
ok = false;
}
changedFiles.clear();
}
if (flushTimerTask != null) {
flushTimerTask.cancel();
flushTimerTask = null;
}
return ok;
}
// Mark this prefs file as changed. The changes will be flushed in
// at most flushDelay() seconds.
// Must be called when synchronized on MacOSXPreferencesFile.class
private void markChanged()
{
// Add this file to the changed file list
if (changedFiles == null)
changedFiles = new HashSet<>();
changedFiles.add(this);
// Schedule a new flush and a shutdown hook, if necessary
if (flushTimerTask == null) {
flushTimerTask = new FlushTask();
timer().schedule(flushTimerTask, flushDelay() * 1000);
}
}
// Return the flush delay, initializing from a property if necessary.
private static synchronized long flushDelay()
{
if (flushDelay == -1) {
try {
// flush delay >= 5, default 60
flushDelay = Math.max(5, Integer.parseInt(System.getProperty("java.util.prefs.flushDelay", "60")));
} catch (NumberFormatException e) {
flushDelay = 60;
}
}
return flushDelay;
}
// Initialize and run the sync timer, if the sync timer property is set
// and the sync timer hasn't already been started.
private static synchronized void initSyncTimerIfNeeded()
{
// syncInterval: -1 is uninitialized, other negative is off,
// positive is seconds between syncs (min 5).
if (syncInterval == -1) {
try {
syncInterval = Integer.parseInt(System.getProperty("java.util.prefs.syncInterval", "-2"));
if (syncInterval >= 0) {
// minimum of 5 seconds
syncInterval = Math.max(5, syncInterval);
} else {
syncInterval = -2; // default off
}
} catch (NumberFormatException e) {
syncInterval = -2; // bad property value - default off
}
if (syncInterval > 0) {
timer().schedule(new TimerTask() {
@Override
public void run() {
MacOSXPreferencesFile.syncWorld();}
}, syncInterval * 1000, syncInterval * 1000);
} else {
// syncInterval property not set. No sync timer ever.
}
}
}
// Return the timer used for flush and sync, creating it if necessary.
private static synchronized Timer timer()
{
if (timer == null) {
timer = new Timer(true); // daemon
Thread flushThread =
new Thread(null, null, "Flush Thread", 0, false) {
@Override
public void run() {
flushWorld();
}
};
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
flushThread.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(flushThread);
}
return timer;
}
// Node manipulation
boolean addNode(String path)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
return addNode(path, appName, user, host);
}
}
void removeNode(String path)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
removeNode(path, appName, user, host);
}
}
boolean addChildToNode(String path, String child)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
return addChildToNode(path, child+"/", appName, user, host);
}
}
void removeChildFromNode(String path, String child)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
removeChildFromNode(path, child+"/", appName, user, host);
}
}
// Key manipulation
void addKeyToNode(String path, String key, String value)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
addKeyToNode(path, key, value, appName, user, host);
}
}
void removeKeyFromNode(String path, String key)
{
synchronized(MacOSXPreferencesFile.class) {
markChanged();
removeKeyFromNode(path, key, appName, user, host);
}
}
String getKeyFromNode(String path, String key)
{
synchronized(MacOSXPreferencesFile.class) {
return getKeyFromNode(path, key, appName, user, host);
}
}
// Enumerators
String[] getChildrenForNode(String path)
{
synchronized(MacOSXPreferencesFile.class) {
return getChildrenForNode(path, appName, user, host);
}
}
String[] getKeysForNode(String path)
{
synchronized(MacOSXPreferencesFile.class) {
return getKeysForNode(path, appName, user, host);
}
}
// Synchronization
boolean synchronize()
{
synchronized(MacOSXPreferencesFile.class) {
return synchronize(appName, user, host);
}
}
// CF functions
// Must be called when synchronized on MacOSXPreferencesFile.class
private static final native boolean
addNode(String path, String name, long user, long host);
private static final native void
removeNode(String path, String name, long user, long host);
private static final native boolean
addChildToNode(String path, String child,
String name, long user, long host);
private static final native void
removeChildFromNode(String path, String child,
String name, long user, long host);
private static final native void
addKeyToNode(String path, String key, String value,
String name, long user, long host);
private static final native void
removeKeyFromNode(String path, String key,
String name, long user, long host);
private static final native String
getKeyFromNode(String path, String key,
String name, long user, long host);
private static final native String[]
getChildrenForNode(String path, String name, long user, long host);
private static final native String[]
getKeysForNode(String path, String name, long user, long host);
private static final native boolean
synchronize(String name, long user, long host);
// CFPreferences host and user values (CFStringRefs)
private static long cfCurrentUser = currentUser();
private static long cfAnyUser = anyUser();
private static long cfCurrentHost = currentHost();
private static long cfAnyHost = anyHost();
// CFPreferences constant accessors
private static final native long currentUser();
private static final native long anyUser();
private static final native long currentHost();
private static final native long anyHost();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.io.NotSerializableException;
/**
* Thrown to indicate that a preferences operation could not complete because
* of a failure in the backing store, or a failure to contact the backing
* store.
*
* @author Josh Bloch
* @since 1.4
*/
public class BackingStoreException extends Exception {
/**
* Constructs a BackingStoreException with the specified detail message.
*
* @param s the detail message.
*/
public BackingStoreException(String s) {
super(s);
}
/**
* Constructs a BackingStoreException with the specified cause.
*
* @param cause the cause
*/
public BackingStoreException(Throwable cause) {
super(cause);
}
private static final long serialVersionUID = 859796500401108469L;
}

View file

@ -0,0 +1,261 @@
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
/**
* Static methods for translating Base64 encoded strings to byte arrays
* and vice-versa.
*
* @author Josh Bloch
* @see Preferences
* @since 1.4
*/
class Base64 {
/**
* Translates the specified byte array into a Base64 string as per
* Preferences.put(byte[]).
*/
static String byteArrayToBase64(byte[] a) {
return byteArrayToBase64(a, false);
}
/**
* Translates the specified byte array into an "alternate representation"
* Base64 string. This non-standard variant uses an alphabet that does
* not contain the uppercase alphabetic characters, which makes it
* suitable for use in situations where case-folding occurs.
*/
static String byteArrayToAltBase64(byte[] a) {
return byteArrayToBase64(a, true);
}
private static String byteArrayToBase64(byte[] a, boolean alternate) {
int aLen = a.length;
int numFullGroups = aLen/3;
int numBytesInPartialGroup = aLen - 3*numFullGroups;
int resultLen = 4*((aLen + 2)/3);
StringBuilder result = new StringBuilder(resultLen);
char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
// Translate all full groups from byte array elements to Base64
int inCursor = 0;
for (int i=0; i<numFullGroups; i++) {
int byte0 = a[inCursor++] & 0xff;
int byte1 = a[inCursor++] & 0xff;
int byte2 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
result.append(intToAlpha[byte2 & 0x3f]);
}
// Translate partial group if present
if (numBytesInPartialGroup != 0) {
int byte0 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
if (numBytesInPartialGroup == 1) {
result.append(intToAlpha[(byte0 << 4) & 0x3f]);
result.append("==");
} else {
// assert numBytesInPartialGroup == 2;
int byte1 = a[inCursor++] & 0xff;
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f]);
result.append('=');
}
}
// assert inCursor == a.length;
// assert result.length() == resultLen;
return result.toString();
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in Table 1 of RFC 2045.
*/
private static final char intToBase64[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Alternate Base64 Alphabet" equivalents.
* This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045.
* This alternate alphabet does not use the capital letters. It is
* designed for use in environments where "case folding" occurs.
*/
private static final char intToAltBase64[] = {
'!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?'
};
/**
* Translates the specified Base64 string (as per Preferences.get(byte[]))
* into a byte array.
*
* @throws IllegalArgumentException if {@code s} is not a valid Base64
* string.
*/
static byte[] base64ToByteArray(String s) {
return base64ToByteArray(s, false);
}
/**
* Translates the specified "alternate representation" Base64 string
* into a byte array.
*
* @throws IllegalArgumentException or ArrayOutOfBoundsException
* if {@code s} is not a valid alternate representation
* Base64 string.
*/
static byte[] altBase64ToByteArray(String s) {
return base64ToByteArray(s, true);
}
private static byte[] base64ToByteArray(String s, boolean alternate) {
byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);
int sLen = s.length();
int numGroups = sLen/4;
if (4*numGroups != sLen)
throw new IllegalArgumentException(
"String length must be a multiple of four.");
int missingBytesInLastGroup = 0;
int numFullGroups = numGroups;
if (sLen != 0) {
if (s.charAt(sLen-1) == '=') {
missingBytesInLastGroup++;
numFullGroups--;
}
if (s.charAt(sLen-2) == '=')
missingBytesInLastGroup++;
}
byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
// Translate all full groups from base64 to byte array elements
int inCursor = 0, outCursor = 0;
for (int i=0; i<numFullGroups; i++) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
result[outCursor++] = (byte) ((ch2 << 6) | ch3);
}
// Translate partial group, if present
if (missingBytesInLastGroup != 0) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
if (missingBytesInLastGroup == 1) {
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
}
}
// assert inCursor == s.length()-missingBytesInLastGroup;
// assert outCursor == result.length;
return result;
}
/**
* Translates the specified character, which is assumed to be in the
* "Base 64 Alphabet" into its equivalent 6-bit positive integer.
*
* @throws IllegalArgumentException or ArrayOutOfBoundsException if
* c is not in the Base64 Alphabet.
*/
private static int base64toInt(char c, byte[] alphaToInt) {
int result = alphaToInt[c];
if (result < 0)
throw new IllegalArgumentException("Illegal character " + c);
return result;
}
/**
* This array is a lookup table that translates unicode characters
* drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
* into their 6-bit positive integer equivalents. Characters that
* are not in the Base64 alphabet but fall within the bounds of the
* array are translated to -1.
*/
private static final byte base64ToInt[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
/**
* This array is the analogue of base64ToInt, but for the nonstandard
* variant that avoids the use of uppercase alphabetic characters.
*/
private static final byte altBase64ToInt[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 22, 23, 24, 25
};
public static void main(String args[]) {
int numRuns = Integer.parseInt(args[0]);
int numBytes = Integer.parseInt(args[1]);
java.util.Random rnd = new java.util.Random();
for (int i=0; i<numRuns; i++) {
for (int j=0; j<numBytes; j++) {
byte[] arr = new byte[j];
for (int k=0; k<j; k++)
arr[k] = (byte)rnd.nextInt();
String s = byteArrayToBase64(arr);
byte [] b = base64ToByteArray(s);
if (!java.util.Arrays.equals(arr, b))
System.out.println("Dismal failure!");
s = byteArrayToAltBase64(arr);
b = altBase64ToByteArray(s);
if (!java.util.Arrays.equals(arr, b))
System.out.println("Alternate dismal failure!");
}
}
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.io.NotSerializableException;
/**
* Thrown to indicate that an operation could not complete because
* the input did not conform to the appropriate XML document type
* for a collection of preferences, as per the {@link Preferences}
* specification.
*
* @author Josh Bloch
* @see Preferences
* @since 1.4
*/
public class InvalidPreferencesFormatException extends Exception {
/**
* Constructs an InvalidPreferencesFormatException with the specified
* cause.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method).
*/
public InvalidPreferencesFormatException(Throwable cause) {
super(cause);
}
/**
* Constructs an InvalidPreferencesFormatException with the specified
* detail message.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link Throwable#getMessage()} method.
*/
public InvalidPreferencesFormatException(String message) {
super(message);
}
/**
* Constructs an InvalidPreferencesFormatException with the specified
* detail message and cause.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link Throwable#getMessage()} method.
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method).
*/
public InvalidPreferencesFormatException(String message, Throwable cause) {
super(message, cause);
}
private static final long serialVersionUID = -791715184232119669L;
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.io.NotSerializableException;
/**
* An event emitted by a {@code Preferences} node to indicate that
* a child of that node has been added or removed.<p>
*
* Note, that although NodeChangeEvent inherits Serializable interface from
* java.util.EventObject, it is not intended to be Serializable. Appropriate
* serialization methods are implemented to throw NotSerializableException.
*
* @author Josh Bloch
* @see Preferences
* @see NodeChangeListener
* @see PreferenceChangeEvent
* @since 1.4
* @serial exclude
*/
public class NodeChangeEvent extends java.util.EventObject {
/**
* The node that was added or removed.
*
* @serial
*/
private Preferences child;
/**
* Constructs a new {@code NodeChangeEvent} instance.
*
* @param parent The parent of the node that was added or removed.
* @param child The node that was added or removed.
*/
public NodeChangeEvent(Preferences parent, Preferences child) {
super(parent);
this.child = child;
}
/**
* Returns the parent of the node that was added or removed.
*
* @return The parent Preferences node whose child was added or removed
*/
public Preferences getParent() {
return (Preferences) getSource();
}
/**
* Returns the node that was added or removed.
*
* @return The node that was added or removed.
*/
public Preferences getChild() {
return child;
}
/**
* Throws NotSerializableException, since NodeChangeEvent objects are not
* intended to be serializable.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws NotSerializableException {
throw new NotSerializableException("Not serializable.");
}
/**
* Throws NotSerializableException, since NodeChangeEvent objects are not
* intended to be serializable.
*/
private void readObject(java.io.ObjectInputStream in)
throws NotSerializableException {
throw new NotSerializableException("Not serializable.");
}
// Defined so that this class isn't flagged as a potential problem when
// searches for missing serialVersionUID fields are done.
private static final long serialVersionUID = 8068949086596572957L;
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
/**
* A listener for receiving preference node change events.
*
* @author Josh Bloch
* @see Preferences
* @see NodeChangeEvent
* @see PreferenceChangeListener
* @since 1.4
*/
public interface NodeChangeListener extends java.util.EventListener {
/**
* This method gets called when a child node is added.
*
* @param evt A node change event object describing the parent
* and child node.
*/
void childAdded(NodeChangeEvent evt);
/**
* This method gets called when a child node is removed.
*
* @param evt A node change event object describing the parent
* and child node.
*/
void childRemoved(NodeChangeEvent evt);
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.io.NotSerializableException;
/**
* An event emitted by a {@code Preferences} node to indicate that
* a preference has been added, removed or has had its value changed.<p>
*
* Note, that although PreferenceChangeEvent inherits Serializable interface
* from EventObject, it is not intended to be Serializable. Appropriate
* serialization methods are implemented to throw NotSerializableException.
*
* @author Josh Bloch
* @see Preferences
* @see PreferenceChangeListener
* @see NodeChangeEvent
* @since 1.4
* @serial exclude
*/
public class PreferenceChangeEvent extends java.util.EventObject {
/**
* Key of the preference that changed.
*
* @serial
*/
private String key;
/**
* New value for preference, or {@code null} if it was removed.
*
* @serial
*/
private String newValue;
/**
* Constructs a new {@code PreferenceChangeEvent} instance.
*
* @param node The Preferences node that emitted the event.
* @param key The key of the preference that was changed.
* @param newValue The new value of the preference, or {@code null}
* if the preference is being removed.
*/
public PreferenceChangeEvent(Preferences node, String key,
String newValue) {
super(node);
this.key = key;
this.newValue = newValue;
}
/**
* Returns the preference node that emitted the event.
*
* @return The preference node that emitted the event.
*/
public Preferences getNode() {
return (Preferences) getSource();
}
/**
* Returns the key of the preference that was changed.
*
* @return The key of the preference that was changed.
*/
public String getKey() {
return key;
}
/**
* Returns the new value for the preference.
*
* @return The new value for the preference, or {@code null} if the
* preference was removed.
*/
public String getNewValue() {
return newValue;
}
/**
* Throws NotSerializableException, since NodeChangeEvent objects
* are not intended to be serializable.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws NotSerializableException {
throw new NotSerializableException("Not serializable.");
}
/**
* Throws NotSerializableException, since PreferenceChangeEvent objects
* are not intended to be serializable.
*/
private void readObject(java.io.ObjectInputStream in)
throws NotSerializableException {
throw new NotSerializableException("Not serializable.");
}
// Defined so that this class isn't flagged as a potential problem when
// searches for missing serialVersionUID fields are done.
private static final long serialVersionUID = 793724513368024975L;
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
/**
* A listener for receiving preference change events.
*
* @author Josh Bloch
* @see Preferences
* @see PreferenceChangeEvent
* @see NodeChangeListener
* @since 1.4
*/
@FunctionalInterface
public interface PreferenceChangeListener extends java.util.EventListener {
/**
* This method gets called when a preference is added, removed or when
* its value is changed.
*
* @param evt A PreferenceChangeEvent object describing the event source
* and the preference that has changed.
*/
void preferenceChange(PreferenceChangeEvent evt);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.util.*;
/**
* A factory object that generates Preferences objects. Providers of
* new {@link Preferences} implementations should provide corresponding
* {@code PreferencesFactory} implementations so that the new
* {@code Preferences} implementation can be installed in place of the
* platform-specific default implementation.
*
* <p><strong>This class is for {@code Preferences} implementers only.
* Normal users of the {@code Preferences} facility should have no need to
* consult this documentation.</strong>
*
* @author Josh Bloch
* @see Preferences
* @since 1.4
*/
public interface PreferencesFactory {
/**
* Returns the system root preference node. (Multiple calls on this
* method will return the same object reference.)
* @return the system root preference node
*/
Preferences systemRoot();
/**
* Returns the user root preference node corresponding to the calling
* user. In a server, the returned value will typically depend on
* some implicit client-context.
* @return the user root preference node corresponding to the calling
* user
*/
Preferences userRoot();
}

View file

@ -0,0 +1,420 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.w3c.dom.*;
/**
* XML Support for java.util.prefs. Methods to import and export preference
* nodes and subtrees.
*
* @author Josh Bloch and Mark Reinhold
* @see Preferences
* @since 1.4
*/
class XmlSupport {
// The required DTD URI for exported preferences
private static final String PREFS_DTD_URI =
"http://java.sun.com/dtd/preferences.dtd";
// The actual DTD corresponding to the URI
private static final String PREFS_DTD =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<!-- DTD for preferences -->" +
"<!ELEMENT preferences (root) >" +
"<!ATTLIST preferences" +
" EXTERNAL_XML_VERSION CDATA \"0.0\" >" +
"<!ELEMENT root (map, node*) >" +
"<!ATTLIST root" +
" type (system|user) #REQUIRED >" +
"<!ELEMENT node (map, node*) >" +
"<!ATTLIST node" +
" name CDATA #REQUIRED >" +
"<!ELEMENT map (entry*) >" +
"<!ATTLIST map" +
" MAP_XML_VERSION CDATA \"0.0\" >" +
"<!ELEMENT entry EMPTY >" +
"<!ATTLIST entry" +
" key CDATA #REQUIRED" +
" value CDATA #REQUIRED >" ;
/**
* Version number for the format exported preferences files.
*/
private static final String EXTERNAL_XML_VERSION = "1.0";
/*
* Version number for the internal map files.
*/
private static final String MAP_XML_VERSION = "1.0";
/**
* Export the specified preferences node and, if subTree is true, all
* subnodes, to the specified output stream. Preferences are exported as
* an XML document conforming to the definition in the Preferences spec.
*
* @throws IOException if writing to the specified output stream
* results in an {@code IOException}.
* @throws BackingStoreException if preference data cannot be read from
* backing store.
* @throws IllegalStateException if this node (or an ancestor) has been
* removed with the {@link Preferences#removeNode()} method.
*/
static void export(OutputStream os, final Preferences p, boolean subTree)
throws IOException, BackingStoreException {
if (((AbstractPreferences)p).isRemoved())
throw new IllegalStateException("Node has been removed");
Document doc = createPrefsDoc("preferences");
Element preferences = doc.getDocumentElement() ;
preferences.setAttribute("EXTERNAL_XML_VERSION", EXTERNAL_XML_VERSION);
Element xmlRoot = (Element)
preferences.appendChild(doc.createElement("root"));
xmlRoot.setAttribute("type", (p.isUserNode() ? "user" : "system"));
// Get bottom-up list of nodes from p to root, excluding root
List<Preferences> ancestors = new ArrayList<>();
for (Preferences kid = p, dad = kid.parent(); dad != null;
kid = dad, dad = kid.parent()) {
ancestors.add(kid);
}
Element e = xmlRoot;
for (int i=ancestors.size()-1; i >= 0; i--) {
e.appendChild(doc.createElement("map"));
e = (Element) e.appendChild(doc.createElement("node"));
e.setAttribute("name", ancestors.get(i).name());
}
putPreferencesInXml(e, doc, p, subTree);
writeDoc(doc, os);
}
/**
* Put the preferences in the specified Preferences node into the
* specified XML element which is assumed to represent a node
* in the specified XML document which is assumed to conform to
* PREFS_DTD. If subTree is true, create children of the specified
* XML node conforming to all of the children of the specified
* Preferences node and recurse.
*
* @throws BackingStoreException if it is not possible to read
* the preferences or children out of the specified
* preferences node.
*/
private static void putPreferencesInXml(Element elt, Document doc,
Preferences prefs, boolean subTree) throws BackingStoreException
{
Preferences[] kidsCopy = null;
String[] kidNames = null;
// Node is locked to export its contents and get a
// copy of children, then lock is released,
// and, if subTree = true, recursive calls are made on children
synchronized (((AbstractPreferences)prefs).lock) {
// Check if this node was concurrently removed. If yes
// remove it from XML Document and return.
if (((AbstractPreferences)prefs).isRemoved()) {
elt.getParentNode().removeChild(elt);
return;
}
// Put map in xml element
String[] keys = prefs.keys();
Element map = (Element) elt.appendChild(doc.createElement("map"));
for (String key : keys) {
Element entry = (Element)
map.appendChild(doc.createElement("entry"));
entry.setAttribute("key", key);
// NEXT STATEMENT THROWS NULL PTR EXC INSTEAD OF ASSERT FAIL
entry.setAttribute("value", prefs.get(key, null));
}
// Recurse if appropriate
if (subTree) {
/* Get a copy of kids while lock is held */
kidNames = prefs.childrenNames();
kidsCopy = new Preferences[kidNames.length];
for (int i = 0; i < kidNames.length; i++)
kidsCopy[i] = prefs.node(kidNames[i]);
}
// release lock
}
if (subTree) {
for (int i=0; i < kidNames.length; i++) {
Element xmlKid = (Element)
elt.appendChild(doc.createElement("node"));
xmlKid.setAttribute("name", kidNames[i]);
putPreferencesInXml(xmlKid, doc, kidsCopy[i], subTree);
}
}
}
/**
* Import preferences from the specified input stream, which is assumed
* to contain an XML document in the format described in the Preferences
* spec.
*
* @throws IOException if reading from the specified output stream
* results in an {@code IOException}.
* @throws InvalidPreferencesFormatException Data on input stream does not
* constitute a valid XML document with the mandated document type.
*/
static void importPreferences(InputStream is)
throws IOException, InvalidPreferencesFormatException
{
try {
Document doc = loadPrefsDoc(is);
String xmlVersion =
doc.getDocumentElement().getAttribute("EXTERNAL_XML_VERSION");
if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0)
throw new InvalidPreferencesFormatException(
"Exported preferences file format version " + xmlVersion +
" is not supported. This java installation can read" +
" versions " + EXTERNAL_XML_VERSION + " or older. You may need" +
" to install a newer version of JDK.");
Element xmlRoot = (Element) doc.getDocumentElement().
getChildNodes().item(0);
Preferences prefsRoot =
(xmlRoot.getAttribute("type").equals("user") ?
Preferences.userRoot() : Preferences.systemRoot());
ImportSubtree(prefsRoot, xmlRoot);
} catch(SAXException e) {
throw new InvalidPreferencesFormatException(e);
}
}
/**
* Create a new prefs XML document.
*/
private static Document createPrefsDoc( String qname ) {
try {
DOMImplementation di = DocumentBuilderFactory.newInstance().
newDocumentBuilder().getDOMImplementation();
DocumentType dt = di.createDocumentType(qname, null, PREFS_DTD_URI);
return di.createDocument(null, qname, dt);
} catch(ParserConfigurationException e) {
throw new AssertionError(e);
}
}
/**
* Load an XML document from specified input stream, which must
* have the requisite DTD URI.
*/
private static Document loadPrefsDoc(InputStream in)
throws SAXException, IOException
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);
dbf.setValidating(true);
dbf.setCoalescing(true);
dbf.setIgnoringComments(true);
try {
DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver(new Resolver());
db.setErrorHandler(new EH());
return db.parse(new InputSource(in));
} catch (ParserConfigurationException e) {
throw new AssertionError(e);
}
}
/**
* Write XML document to the specified output stream.
*/
private static final void writeDoc(Document doc, OutputStream out)
throws IOException
{
try {
TransformerFactory tf = TransformerFactory.newInstance();
try {
tf.setAttribute("indent-number", 2);
} catch (IllegalArgumentException iae) {
//Ignore the IAE. Should not fail the writeout even the
//transformer provider does not support "indent-number".
}
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
t.setOutputProperty(OutputKeys.INDENT, "yes");
//Transformer resets the "indent" info if the "result" is a StreamResult with
//an OutputStream object embedded, creating a Writer object on top of that
//OutputStream object however works.
t.transform(new DOMSource(doc),
new StreamResult(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
} catch(TransformerException e) {
throw new AssertionError(e);
}
}
/**
* Recursively traverse the specified preferences node and store
* the described preferences into the system or current user
* preferences tree, as appropriate.
*/
private static void ImportSubtree(Preferences prefsNode, Element xmlNode) {
NodeList xmlKids = xmlNode.getChildNodes();
int numXmlKids = xmlKids.getLength();
/*
* We first lock the node, import its contents and get
* child nodes. Then we unlock the node and go to children
* Since some of the children might have been concurrently
* deleted we check for this.
*/
Preferences[] prefsKids;
/* Lock the node */
synchronized (((AbstractPreferences)prefsNode).lock) {
//If removed, return silently
if (((AbstractPreferences)prefsNode).isRemoved())
return;
// Import any preferences at this node
Element firstXmlKid = (Element) xmlKids.item(0);
ImportPrefs(prefsNode, firstXmlKid);
prefsKids = new Preferences[numXmlKids - 1];
// Get involved children
for (int i=1; i < numXmlKids; i++) {
Element xmlKid = (Element) xmlKids.item(i);
prefsKids[i-1] = prefsNode.node(xmlKid.getAttribute("name"));
}
} // unlocked the node
// import children
for (int i=1; i < numXmlKids; i++)
ImportSubtree(prefsKids[i-1], (Element)xmlKids.item(i));
}
/**
* Import the preferences described by the specified XML element
* (a map from a preferences document) into the specified
* preferences node.
*/
private static void ImportPrefs(Preferences prefsNode, Element map) {
NodeList entries = map.getChildNodes();
for (int i=0, numEntries = entries.getLength(); i < numEntries; i++) {
Element entry = (Element) entries.item(i);
prefsNode.put(entry.getAttribute("key"),
entry.getAttribute("value"));
}
}
/**
* Export the specified Map<String,String> to a map document on
* the specified OutputStream as per the prefs DTD. This is used
* as the internal (undocumented) format for FileSystemPrefs.
*
* @throws IOException if writing to the specified output stream
* results in an {@code IOException}.
*/
static void exportMap(OutputStream os, Map<String, String> map) throws IOException {
Document doc = createPrefsDoc("map");
Element xmlMap = doc.getDocumentElement( ) ;
xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION);
for (Map.Entry<String, String> e : map.entrySet()) {
Element xe = (Element)
xmlMap.appendChild(doc.createElement("entry"));
xe.setAttribute("key", e.getKey());
xe.setAttribute("value", e.getValue());
}
writeDoc(doc, os);
}
/**
* Import Map from the specified input stream, which is assumed
* to contain a map document as per the prefs DTD. This is used
* as the internal (undocumented) format for FileSystemPrefs. The
* key-value pairs specified in the XML document will be put into
* the specified Map. (If this Map is empty, it will contain exactly
* the key-value pairs int the XML-document when this method returns.)
*
* @throws IOException if reading from the specified output stream
* results in an {@code IOException}.
* @throws InvalidPreferencesFormatException Data on input stream does not
* constitute a valid XML document with the mandated document type.
*/
static void importMap(InputStream is, Map<String, String> m)
throws IOException, InvalidPreferencesFormatException
{
try {
Document doc = loadPrefsDoc(is);
Element xmlMap = doc.getDocumentElement();
// check version
String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");
if (mapVersion.compareTo(MAP_XML_VERSION) > 0)
throw new InvalidPreferencesFormatException(
"Preferences map file format version " + mapVersion +
" is not supported. This java installation can read" +
" versions " + MAP_XML_VERSION + " or older. You may need" +
" to install a newer version of JDK.");
NodeList entries = xmlMap.getChildNodes();
for (int i=0, numEntries=entries.getLength(); i<numEntries; i++) {
Element entry = (Element) entries.item(i);
m.put(entry.getAttribute("key"), entry.getAttribute("value"));
}
} catch(SAXException e) {
throw new InvalidPreferencesFormatException(e);
}
}
private static class Resolver implements EntityResolver {
public InputSource resolveEntity(String pid, String sid)
throws SAXException
{
if (sid.equals(PREFS_DTD_URI)) {
InputSource is;
is = new InputSource(new StringReader(PREFS_DTD));
is.setSystemId(PREFS_DTD_URI);
return is;
}
throw new SAXException("Invalid system identifier: " + sid);
}
}
private static class EH implements ErrorHandler {
public void error(SAXParseException x) throws SAXException {
throw x;
}
public void fatalError(SAXParseException x) throws SAXException {
throw x;
}
public void warning(SAXParseException x) throws SAXException {
throw x;
}
}
}

View file

@ -0,0 +1,44 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<!--
Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
-->
</head>
<body bgcolor="white">
This package allows applications to store and retrieve user and system
preference and configuration data. This data is stored persistently in an
implementation-dependent backing store. There are two separate trees of
preference nodes, one for user preferences and one for system preferences.
<!--
<h2>Package Specification</h2>
<h2>Related Documentation</h2>
-->
@since 1.4
</body>
</html>

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Defines the Preferences API.
*
* @uses java.util.prefs.PreferencesFactory
*
* @moduleGraph
* @since 9
*/
module java.prefs {
requires java.xml;
exports java.util.prefs;
uses java.util.prefs.PreferencesFactory;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
/**
* Factory for FileSystemPreferences. This class allows FileSystemPreferences
* to be installed as the Preferences implementations via the
* java.util.prefs.PreferencesFactory system property.
*
* @author Josh Bloch
* @see FileSystemPreferences
* @see Preferences
* @since 1.4
*/
class FileSystemPreferencesFactory implements PreferencesFactory {
public Preferences userRoot() {
return FileSystemPreferences.getUserRoot();
}
public Preferences systemRoot() {
return FileSystemPreferences.getSystemRoot();
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Solaris/Linux platform specific code to support the Prefs API.
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <utime.h>
#include "jni_util.h"
/*
* Declare library specific JNI_Onload entry if static build
*/
DEF_STATIC_JNI_OnLoad
JNIEXPORT jint JNICALL
Java_java_util_prefs_FileSystemPreferences_chmod(JNIEnv *env,
jclass thisclass, jstring java_fname, jint permission) {
const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL);
int result = -1;
if (fname) {
result = chmod(fname, permission);
if (result != 0)
result = errno;
JNU_ReleaseStringPlatformChars(env, java_fname, fname);
}
return (jint) result;
}
#if defined(_ALLBSD_SOURCE)
typedef struct flock FLOCK;
#else
typedef struct flock64 FLOCK;
#endif
/**
* Try to open a named lock file.
* The result is a cookie that can be used later to unlock the file.
* On failure the result is zero.
*/
JNIEXPORT jintArray JNICALL
Java_java_util_prefs_FileSystemPreferences_lockFile0(JNIEnv *env,
jclass thisclass, jstring java_fname, jint permission, jboolean shared) {
const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL);
int fd, rc;
int result[2];
jintArray javaResult = NULL;
int old_umask;
FLOCK fl;
if (!fname)
return javaResult;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_start = 0;
if (shared == JNI_TRUE) {
fl.l_type = F_RDLCK;
} else {
fl.l_type = F_WRLCK;
}
if (shared == JNI_TRUE) {
fd = open(fname, O_RDONLY, 0);
} else {
old_umask = umask(0);
fd = open(fname, O_WRONLY|O_CREAT, permission);
result[1] = errno;
umask(old_umask);
}
if (fd < 0) {
result[0] = 0;
} else {
#if defined(_ALLBSD_SOURCE)
rc = fcntl(fd, F_SETLK, &fl);
#else
rc = fcntl(fd, F_SETLK64, &fl);
#endif
result[1] = errno;
if (rc < 0) {
result[0]= 0;
close(fd);
} else {
result[0] = fd;
}
}
JNU_ReleaseStringPlatformChars(env, java_fname, fname);
javaResult = (*env)->NewIntArray(env,2);
if (javaResult)
(*env)->SetIntArrayRegion(env, javaResult, 0, 2, result);
return javaResult;
}
/**
* Try to unlock a lock file, using a cookie returned by lockFile.
*/
JNIEXPORT jint JNICALL
Java_java_util_prefs_FileSystemPreferences_unlockFile0(JNIEnv *env,
jclass thisclass, jint fd) {
int rc;
FLOCK fl;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_start = 0;
fl.l_type = F_UNLCK;
#if defined(_ALLBSD_SOURCE)
rc = fcntl(fd, F_SETLK, &fl);
#else
rc = fcntl(fd, F_SETLK64, &fl);
#endif
if (rc < 0) {
close(fd);
return (jint)errno;
}
rc = close(fd);
if (rc < 0) {
return (jint) errno;
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.prefs;
/**
* Implementation of {@code PreferencesFactory} to return
* WindowsPreferences objects.
*
* @author Konstantin Kladko
* @see Preferences
* @see WindowsPreferences
* @since 1.4
*/
class WindowsPreferencesFactory implements PreferencesFactory {
/**
* Returns WindowsPreferences.userRoot
*/
public Preferences userRoot() {
return WindowsPreferences.getUserRoot();
}
/**
* Returns WindowsPreferences.systemRoot
*/
public Preferences systemRoot() {
return WindowsPreferences.getSystemRoot();
}
}

View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <stdlib.h>
#include <windows.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Declare library specific JNI_Onload entry if static build
*/
DEF_STATIC_JNI_OnLoad
JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegOpenKey
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey, jint securityMask) {
HKEY handle;
char* str;
int tmp[2];
int errorCode=-1;
jintArray result;
str = (*env)->GetByteArrayElements(env, lpSubKey, NULL);
CHECK_NULL_RETURN(str, NULL);
errorCode = RegOpenKeyEx((HKEY)hKey, str, 0, securityMask, &handle);
(*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0);
tmp[0]= (int) handle;
tmp[1]= errorCode;
result = (*env)->NewIntArray(env,2);
if (result != NULL) {
(*env)->SetIntArrayRegion(env, result, 0, 2, tmp);
}
return result;
}
JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCloseKey
(JNIEnv* env, jclass this_class, jint hKey) {
return (jint) RegCloseKey((HKEY) hKey);
};
JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCreateKeyEx
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) {
HKEY handle;
char* str;
int tmp[3];
DWORD lpdwDisposition;
int errorCode;
jintArray result = NULL;
str = (*env)->GetByteArrayElements(env, lpSubKey, NULL);
CHECK_NULL_RETURN(str, NULL);
errorCode = RegCreateKeyEx((HKEY)hKey, str, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_READ,
NULL, &handle, &lpdwDisposition);
(*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0);
tmp[0]= (int) handle;
tmp[1]= errorCode;
tmp[2]= lpdwDisposition;
result = (*env)->NewIntArray(env,3);
if (result != NULL) {
(*env)->SetIntArrayRegion(env, result, 0, 3, tmp);
}
return result;
}
JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteKey
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) {
char* str;
int result;
str = (*env)->GetByteArrayElements(env, lpSubKey, NULL);
CHECK_NULL_RETURN(str, -1);
result = RegDeleteKey((HKEY)hKey, str);
(*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0);
return result;
};
JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegFlushKey
(JNIEnv* env, jclass this_class, jint hKey) {
return RegFlushKey ((HKEY)hKey);
}
JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryValueEx
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) {
char* valueNameStr;
char* buffer;
jbyteArray result;
DWORD valueType;
DWORD valueSize;
valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL);
CHECK_NULL_RETURN(valueNameStr, NULL);
if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, NULL,
&valueSize) != ERROR_SUCCESS) {
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
return NULL;
}
buffer = (char*)malloc(valueSize);
if (buffer != NULL) {
if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, buffer,
&valueSize) != ERROR_SUCCESS) {
free(buffer);
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
return NULL;
}
} else {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
return NULL;
}
if (valueType == REG_SZ) {
result = (*env)->NewByteArray(env, valueSize);
if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, valueSize, buffer);
}
} else {
result = NULL;
}
free(buffer);
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
return result;
}
JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegSetValueEx
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName, jbyteArray data) {
char* valueNameStr;
char* dataStr;
int size = -1;
int nameSize = -1;
int error_code = -1;
if ((valueName == NULL)||(data == NULL)) {return -1;}
size = (*env)->GetArrayLength(env, data);
dataStr = (*env)->GetByteArrayElements(env, data, NULL);
CHECK_NULL_RETURN(dataStr, -1);
valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL);
if (valueNameStr != NULL) {
error_code = RegSetValueEx((HKEY)hKey, valueNameStr, 0,
REG_SZ, dataStr, size);
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
}
(*env)->ReleaseByteArrayElements(env, data, dataStr, 0);
return error_code;
}
JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteValue
(JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) {
char* valueNameStr;
int error_code = -1;
if (valueName == NULL) {return -1;}
valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL);
CHECK_NULL_RETURN(valueNameStr, -1);
error_code = RegDeleteValue((HKEY)hKey, valueNameStr);
(*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0);
return error_code;
}
JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryInfoKey
(JNIEnv* env, jclass this_class, jint hKey) {
jintArray result = NULL;
int tmp[5];
int valuesNumber = -1;
int maxValueNameLength = -1;
int maxSubKeyLength = -1;
int subKeysNumber = -1;
int errorCode = -1;
errorCode = RegQueryInfoKey((HKEY)hKey, NULL, NULL, NULL,
&subKeysNumber, &maxSubKeyLength, NULL,
&valuesNumber, &maxValueNameLength,
NULL, NULL, NULL);
tmp[0]= subKeysNumber;
tmp[1]= (int)errorCode;
tmp[2]= valuesNumber;
tmp[3]= maxSubKeyLength;
tmp[4]= maxValueNameLength;
result = (*env)->NewIntArray(env,5);
if (result != NULL) {
(*env)->SetIntArrayRegion(env, result, 0, 5, tmp);
}
return result;
}
JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumKeyEx
(JNIEnv* env, jclass this_class, jint hKey , jint subKeyIndex, jint maxKeyLength) {
int size = maxKeyLength;
jbyteArray result;
char* buffer = NULL;
buffer = (char*)malloc(maxKeyLength);
if (buffer == NULL) {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
return NULL;
}
if (RegEnumKeyEx((HKEY) hKey, subKeyIndex, buffer, &size, NULL, NULL,
NULL, NULL) != ERROR_SUCCESS){
free(buffer);
return NULL;
}
result = (*env)->NewByteArray(env, size + 1);
if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer);
}
free(buffer);
return result;
}
JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumValue
(JNIEnv* env, jclass this_class, jint hKey , jint valueIndex, jint maxValueNameLength){
int size = maxValueNameLength;
jbyteArray result;
char* buffer = NULL;
int error_code;
buffer = (char*)malloc(maxValueNameLength);
if (buffer == NULL) {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
return NULL;
}
error_code = RegEnumValue((HKEY) hKey, valueIndex, buffer,
&size, NULL, NULL, NULL, NULL);
if (error_code!= ERROR_SUCCESS){
free(buffer);
return NULL;
}
result = (*env)->NewByteArray(env, size + 1);
if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer);
}
free(buffer);
return result;
}
#ifdef __cplusplus
}
#endif