3909N/A * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * Preferences implementation for Unix. Preferences are stored in the file 0N/A * system, with one directory per preferences node. All of the preferences 0N/A * at each node are stored in a single file. Atomic file system operations 0N/A * (e.g. File.renameTo) are used to ensure integrity. An in-memory cache of 0N/A * the "explored" portion of the tree is maintained for performance, and 0N/A * written back to the disk periodically. File-locking is used to ensure 0N/A * reasonable behavior when multiple VMs are running at the same time. 0N/A * (The file lock is obtained only for sync(), flush() and removeNode().) 0N/A * @author Josh Bloch 0N/A * Sync interval in seconds. 28N/A "java.util.prefs.syncInterval",
"30"))));
0N/A * Returns logger for error messages. Backing store exceptions are logged at 0N/A * Directory for system preferences. 0N/A * Flag, indicating whether systemRoot directory is writable 0N/A * Directory for user preferences. 0N/A * Flag, indicating whether userRoot directory is writable 0N/A // Attempt to create root dir if it does not yet exist. 0N/A " on userRoot directory. ");
0N/A " directory. User preferences are unusable.");
0N/A // create if does not exist. 0N/A "mod file. Chmod failed on " +
0N/A // Attempt to create root dir if it does not yet exist. 0N/A // system root does not exist in /etc/.java 0N/A // Switching to java.home 0N/A "Created system preferences directory " 0N/A +
"system preferences directory. System " 0N/A +
"preferences are unusable.");
0N/A // create if does not exist. 0N/A * The lock file for the user tree. 0N/A * The lock file for the system tree. 0N/A * Unix lock handle for userRoot. 0N/A * Zero, if unlocked. 0N/A * Unix lock handle for systemRoot. 0N/A * Zero, if unlocked. 0N/A * The directory representing this preference node. There is no guarantee 0N/A * that this directory exits, as another VM can delete it at any time 0N/A * that it (the other VM) holds the file-lock. While the root node cannot 0N/A * be deleted, it may not yet have been created, or the underlying 0N/A * directory could have been deleted accidentally. 0N/A * The file representing this preference node's preferences. 0N/A * The file format is undocumented, and subject to change 0N/A * from release to release, but I'm sure that you can figure 0N/A * it out if you try real hard. 0N/A * A temporary file used for saving changes to preferences. As part of 0N/A * the sync operation, changes are first saved into this file, and then 0N/A * atomically renamed to prefsFile. This results in an atomic state 0N/A * change from one valid set of preferences to another. The 0N/A * the file-lock is held for the duration of this transformation. 0N/A * File, which keeps track of global modifications of userRoot. 0N/A * Flag, which indicated whether userRoot was modified by another VM 0N/A * Keeps track of userRoot modification time. This time is reset to 0N/A * zero after UNIX reboot, and is increased by 1 second each time 0N/A * userRoot is modified. 0N/A * File, which keeps track of global modifications of systemRoot 0N/A * Flag, which indicates whether systemRoot was modified by another VM 0N/A * Keeps track of systemRoot modification time. This time is reset to 0N/A * zero after system reboot, and is increased by 1 second each time 0N/A * systemRoot is modified. 0N/A * Locally cached preferences for this node (includes uncommitted 0N/A * changes). This map is initialized with from disk when the first get or 0N/A * put operation occurs on this node. It is synchronized with the 0N/A * corresponding disk file (prefsFile) by the sync operation. The initial 0N/A * value is read *without* acquiring the file-lock. 0N/A * The last modification time of the file backing this node at the time 0N/A * that prefCache was last synchronized (or initially read). This 0N/A * value is set *before* reading the file, so it's conservative; the 0N/A * actual timestamp could be (slightly) higher. A value of zero indicates 0N/A * that we were unable to initialize prefsCache from the disk, or 0N/A * have not yet attempted to do so. (If prefsCache is non-null, it 0N/A * indicates the former; if it's null, the latter.) 0N/A * Unix error code for locked file. 0N/A * Unix error code for denied access. 0N/A /* Used to interpret results of native functions */ 0N/A * A list of all uncommitted preference changes. The elements in this 0N/A * list are of type PrefChange. If this node is concurrently modified on 0N/A * disk by another VM, the two sets of changes are merged when this node 0N/A * is sync'ed by overwriting our prefsCache with the preference map last 0N/A * written out to disk (by the other VM), and then replaying this change 0N/A * log against that map. The resulting map is then written back 0N/A * Represents a change to a preference. 0N/A * Reapplies the change to prefsCache. 0N/A * Represents a preference put. 0N/A * Represents a preference remove. 0N/A * Represents the creation of this node. 0N/A * Performs no action, but the presence of this object in changeLog 0N/A * will force the node and its ancestors to be made permanent at the 0N/A * NodeCreate object for this node. 0N/A * Replay changeLog against prefsCache. 0N/A // Add periodic timer task to periodically sync cached prefs 0N/A // Add shutdown hook to flush cached prefs on normal termination 0N/A * Synchronization necessary because userRoot and systemRoot are 0N/A * lazily initialized. 0N/A * Special constructor for roots (both user and system). This constructor 0N/A * will only be called twice, by the static initializer. 0N/A * Construct a new FileSystemPreferences instance with the specified 0N/A * parent node and name. This constructor, called from childSpi, 0N/A * is used to make every node except for the two //roots. 0N/A // These 2 things guarantee node will get wrtten at next flush/sync 0N/A * Initialize prefsCache if it has yet to be initialized. When this method 0N/A * returns, prefsCache will be non-null. If the data was successfully 0N/A * read from the file, lastSyncTime will be updated. If prefsCache was 0N/A * null, but it was impossible to read the file (because it didn't 0N/A * exist or for any other reason) prefsCache will be initialized to an 0N/A * empty, modifiable Map, and lastSyncTime remain zero. 0N/A // assert lastSyncTime == 0; 0N/A * Attempt to load prefsCache from the backing store. If the attempt 0N/A * succeeds, lastSyncTime will be updated (the new value will typically 0N/A * correspond to the data loaded into the map, but it may be less, 0N/A * if another VM is updating this node concurrently). If the attempt 0N/A * fails, a BackingStoreException is thrown and both prefsCache and 0N/A * lastSyncTime are unaffected by the call. 0N/A // Attempt succeeded; update state 0N/A * Attempt to write back prefsCache to the backing store. If the attempt 0N/A * succeeds, lastSyncTime will be updated (the new value will correspond 0N/A * exactly to the data thust written back, as we hold the file lock, which 0N/A * prevents a concurrent write. If the attempt fails, a 0N/A * BackingStoreException is thrown and both the backing store (prefsFile) 0N/A * and lastSyncTime will be unaffected by this call. This call will 0N/A * NEVER leave prefsFile in a corrupt state. 0N/A // to remove a node we need an exclusive lock 0N/A * Called with file lock held (in addition to node locks). 0N/A // dir should be empty now. If it's not, empty it 0N/A "Found extraneous files when removing node: " 0N/A shared =
false;
/* use exclusive lock for user prefs */ 0N/A /* if can write to system root, use exclusive lock. 0N/A otherwise use shared lock. */ 0N/A return;
// We've never been used, don't bother syncing 0N/A // Prefs at this node were externally modified; read in node and 0N/A // playback any local mods since last sync 0N/A // This node was removed in the background. Playback any changes 0N/A // against a virgin (empty) Map. 0N/A * Attempt succeeded; it's barely possible that the call to 0N/A * lastModified might fail (i.e., return 0), but this would not 0N/A * be a disaster, as lastSyncTime is allowed to lag. 0N/A /* If lastSyncTime did not change, or went back 0N/A * increment by 1 second. Since we hold the lock 0N/A * lastSyncTime always monotonically encreases in the 0N/A * Returns true if the specified character is appropriate for use in 0N/A * Unix directory names. A character is appropriate if it's a printable 0N/A * ASCII character (> 0x1f && < 0x7f) and unequal to slash ('/', 0x2f), 0N/A * dot ('.', 0x2e), or underscore ('_', 0x5f). 0N/A return ch >
0x1f &&
ch <
0x7f &&
ch !=
'/' &&
ch !=
'.' &&
ch !=
'_';
0N/A * Returns the directory name corresponding to the specified node name. 0N/A * Generally, this is just the node name. If the node name includes 0N/A * inappropriate characters (as per isDirChar) it is translated to Base64. 0N/A * with the underscore character ('_', 0x5f) prepended. 0N/A * Translate a string into a byte array by translating each character 0N/A * into two bytes, high-byte first ("big-endian"). 0N/A for (
int i=
0, j=
0; i<
len; i++) {
0N/A * Returns the node name corresponding to the specified directory name. 0N/A * (Inverts the transformation of dirName(String). 0N/A * Try to acquire the appropriate file lock (user or system). If 0N/A * the initial attempt fails, several more attempts are made using 0N/A * an exponential backoff strategy. If all attempts fail, this method 0N/A * @throws SecurityException if file access denied. 0N/A// // If at first, you don't succeed... 0N/A * Checks if unlockFile0() returned an error. Throws a SecurityException, 0N/A * if access denied. Logs a warning otherwise. 0N/A " Lock file access denied.");
0N/A * Locks file using UNIX file locking. 0N/A * @param fileName Absolute file name of the lock file. 0N/A * @return Returns a lock handle, used to unlock the file. 0N/A private static native int[]
0N/A * Unlocks file previously locked by lockFile0(). 0N/A * @param lockHandle Handle to the file lock. 0N/A * @return Returns zero if OK, UNIX error code if failure. 0N/A * Changes UNIX file permissions. 0N/A * Initial time between lock attempts, in ms. The time is doubled 0N/A * after each failing attempt (except the first). 0N/A * Maximum number of lock attempts. 0N/A * Release the the appropriate file lock (user or system). 0N/A * @throws SecurityException if file access denied. 0N/A " Lock file access denied.");