8344337: SecurityManager cleanup in java.prefs module
Reviewed-by: lancea, bpb, rriggs, iris
This commit is contained in:
parent
1c7f34d3dd
commit
4d4cef800a
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,8 +28,6 @@ package java.util.prefs;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
class MacOSXPreferences extends AbstractPreferences {
|
class MacOSXPreferences extends AbstractPreferences {
|
||||||
// fixme need security checks?
|
|
||||||
|
|
||||||
// CF preferences file name for Java nodes with short names
|
// CF preferences file name for Java nodes with short names
|
||||||
// This value is also in MacOSXPreferencesFile.c
|
// This value is also in MacOSXPreferencesFile.c
|
||||||
private static final String defaultAppName = "com.apple.java.util.prefs";
|
private static final String defaultAppName = "com.apple.java.util.prefs";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -82,15 +82,9 @@ class MacOSXPreferencesFile {
|
|||||||
loadPrefsLib();
|
loadPrefsLib();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"removal", "restricted"})
|
@SuppressWarnings("restricted")
|
||||||
private static void loadPrefsLib() {
|
private static void loadPrefsLib() {
|
||||||
java.security.AccessController.doPrivileged(
|
System.loadLibrary("prefs");
|
||||||
new java.security.PrivilegedAction<Void>() {
|
|
||||||
public Void run() {
|
|
||||||
System.loadLibrary("prefs");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FlushTask extends TimerTask {
|
private static class FlushTask extends TimerTask {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,8 +27,6 @@ package java.util.prefs;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides a skeletal implementation of the {@link Preferences}
|
* This class provides a skeletal implementation of the {@link Preferences}
|
||||||
@ -1058,14 +1056,8 @@ public abstract class AbstractPreferences extends Preferences {
|
|||||||
* preference tree, {@code false} if it's in the system
|
* preference tree, {@code false} if it's in the system
|
||||||
* preference tree.
|
* preference tree.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
public boolean isUserNode() {
|
public boolean isUserNode() {
|
||||||
return AccessController.doPrivileged(
|
return root == Preferences.userRoot();
|
||||||
new PrivilegedAction<Boolean>() {
|
|
||||||
public Boolean run() {
|
|
||||||
return root == Preferences.userRoot();
|
|
||||||
}
|
|
||||||
}).booleanValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPreferenceChangeListener(PreferenceChangeListener pcl) {
|
public void addPreferenceChangeListener(PreferenceChangeListener pcl) {
|
||||||
|
@ -30,20 +30,10 @@ import jdk.internal.util.OperatingSystem;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.Permission;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.ServiceConfigurationError;
|
import java.util.ServiceConfigurationError;
|
||||||
|
|
||||||
// These imports needed only as a workaround for a JavaDoc bug
|
|
||||||
import java.lang.RuntimePermission;
|
|
||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Long;
|
|
||||||
import java.lang.Float;
|
|
||||||
import java.lang.Double;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in a hierarchical collection of preference data. This class
|
* A node in a hierarchical collection of preference data. This class
|
||||||
* allows applications to store and retrieve user and system
|
* allows applications to store and retrieve user and system
|
||||||
@ -227,19 +217,10 @@ public abstract class Preferences {
|
|||||||
|
|
||||||
private static final PreferencesFactory factory = factory();
|
private static final PreferencesFactory factory = factory();
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static PreferencesFactory factory() {
|
private static PreferencesFactory factory() {
|
||||||
// 1. Try user-specified system property
|
// 1. Try user-specified system property
|
||||||
String factoryName = AccessController.doPrivileged(
|
String factoryName = System.getProperty("java.util.prefs.PreferencesFactory");
|
||||||
new PrivilegedAction<String>() {
|
|
||||||
public String run() {
|
|
||||||
return System.getProperty(
|
|
||||||
"java.util.prefs.PreferencesFactory");}});
|
|
||||||
if (factoryName != null) {
|
if (factoryName != null) {
|
||||||
// FIXME: This code should be run in a doPrivileged and
|
|
||||||
// not use the context classloader, to avoid being
|
|
||||||
// dependent on the invoking thread.
|
|
||||||
// Checking AllPermission also seems wrong.
|
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
Object result =Class.forName(factoryName, false,
|
Object result =Class.forName(factoryName, false,
|
||||||
@ -250,10 +231,6 @@ public abstract class Preferences {
|
|||||||
try {
|
try {
|
||||||
// workaround for javaws, plugin,
|
// workaround for javaws, plugin,
|
||||||
// load factory class using non-system classloader
|
// load factory class using non-system classloader
|
||||||
SecurityManager sm = System.getSecurityManager();
|
|
||||||
if (sm != null) {
|
|
||||||
sm.checkPermission(new java.security.AllPermission());
|
|
||||||
}
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
Object result = Class.forName(factoryName, false,
|
Object result = Class.forName(factoryName, false,
|
||||||
Thread.currentThread()
|
Thread.currentThread()
|
||||||
@ -267,14 +244,6 @@ public abstract class Preferences {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return AccessController.doPrivileged(
|
|
||||||
new PrivilegedAction<PreferencesFactory>() {
|
|
||||||
public PreferencesFactory run() {
|
|
||||||
return factory1();}});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PreferencesFactory factory1() {
|
|
||||||
// 2. Try service provider interface
|
// 2. Try service provider interface
|
||||||
Iterator<PreferencesFactory> itr = ServiceLoader
|
Iterator<PreferencesFactory> itr = ServiceLoader
|
||||||
.load(PreferencesFactory.class, ClassLoader.getSystemClassLoader())
|
.load(PreferencesFactory.class, ClassLoader.getSystemClassLoader())
|
||||||
@ -427,24 +396,12 @@ public abstract class Preferences {
|
|||||||
return "/" + packageName.replace('.', '/');
|
return "/" + packageName.replace('.', '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This permission object represents the permission required to get
|
|
||||||
* access to the user or system root (which in turn allows for all
|
|
||||||
* other operations).
|
|
||||||
*/
|
|
||||||
private static Permission prefsPerm = new RuntimePermission("preferences");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the root preference node for the calling user.
|
* Returns the root preference node for the calling user.
|
||||||
*
|
*
|
||||||
* @return the root preference node for the calling user.
|
* @return the root preference node for the calling user.
|
||||||
*/
|
*/
|
||||||
public static Preferences userRoot() {
|
public static Preferences userRoot() {
|
||||||
@SuppressWarnings("removal")
|
|
||||||
SecurityManager security = System.getSecurityManager();
|
|
||||||
if (security != null)
|
|
||||||
security.checkPermission(prefsPerm);
|
|
||||||
|
|
||||||
return factory.userRoot();
|
return factory.userRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,11 +411,6 @@ public abstract class Preferences {
|
|||||||
* @return the root preference node for the system.
|
* @return the root preference node for the system.
|
||||||
*/
|
*/
|
||||||
public static Preferences systemRoot() {
|
public static Preferences systemRoot() {
|
||||||
@SuppressWarnings("removal")
|
|
||||||
SecurityManager security = System.getSecurityManager();
|
|
||||||
if (security != null)
|
|
||||||
security.checkPermission(prefsPerm);
|
|
||||||
|
|
||||||
return factory.systemRoot();
|
return factory.systemRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,6 @@ package java.util.prefs;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.PrivilegedExceptionAction;
|
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
import sun.util.logging.PlatformLogger;
|
import sun.util.logging.PlatformLogger;
|
||||||
|
|
||||||
@ -53,13 +50,9 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
loadPrefsLib();
|
loadPrefsLib();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"removal", "restricted"})
|
@SuppressWarnings("restricted")
|
||||||
private static void loadPrefsLib() {
|
private static void loadPrefsLib() {
|
||||||
PrivilegedAction<Void> load = () -> {
|
System.loadLibrary("prefs");
|
||||||
System.loadLibrary("prefs");
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
AccessController.doPrivileged(load);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,8 +60,7 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
private static final int SYNC_INTERVAL = Math.max(1,
|
private static final int SYNC_INTERVAL = Math.max(1,
|
||||||
AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
|
Integer.getInteger("java.util.prefs.syncInterval", 30));
|
||||||
Integer.getInteger("java.util.prefs.syncInterval", 30)));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns logger for error messages. Backing store exceptions are logged at
|
* Returns logger for error messages. Backing store exceptions are logged at
|
||||||
@ -117,52 +109,47 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static void setupUserRoot() {
|
private static void setupUserRoot() {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
userRootDir =
|
||||||
public Void run() {
|
new File(System.getProperty("java.util.prefs.userRoot",
|
||||||
userRootDir =
|
|
||||||
new File(System.getProperty("java.util.prefs.userRoot",
|
|
||||||
System.getProperty("user.home")), ".java/.userPrefs");
|
System.getProperty("user.home")), ".java/.userPrefs");
|
||||||
// Attempt to create root dir if it does not yet exist.
|
// Attempt to create root dir if it does not yet exist.
|
||||||
if (!userRootDir.exists()) {
|
if (!userRootDir.exists()) {
|
||||||
if (userRootDir.mkdirs()) {
|
if (userRootDir.mkdirs()) {
|
||||||
try {
|
|
||||||
chmod(userRootDir.getCanonicalPath(), USER_RWX);
|
|
||||||
} catch (IOException e) {
|
|
||||||
getLogger().warning("Could not change permissions" +
|
|
||||||
" on userRoot directory. ");
|
|
||||||
}
|
|
||||||
getLogger().info("Created user preferences directory.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
getLogger().warning("Couldn't create user preferences" +
|
|
||||||
" directory. User preferences are unusable.");
|
|
||||||
}
|
|
||||||
isUserRootWritable = userRootDir.canWrite();
|
|
||||||
String USER_NAME = System.getProperty("user.name");
|
|
||||||
userLockFile = new File (userRootDir,".user.lock." + USER_NAME);
|
|
||||||
userRootModFile = new File (userRootDir,
|
|
||||||
".userRootModFile." + USER_NAME);
|
|
||||||
if (!userRootModFile.exists())
|
|
||||||
try {
|
try {
|
||||||
// create if does not exist.
|
chmod(userRootDir.getCanonicalPath(), USER_RWX);
|
||||||
userRootModFile.createNewFile();
|
|
||||||
// Only user can read/write userRootModFile.
|
|
||||||
int result = chmod(userRootModFile.getCanonicalPath(),
|
|
||||||
USER_READ_WRITE);
|
|
||||||
if (result !=0)
|
|
||||||
getLogger().warning("Problem creating userRoot " +
|
|
||||||
"mod file. Chmod failed on " +
|
|
||||||
userRootModFile.getCanonicalPath() +
|
|
||||||
" Unix error code " + result);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
getLogger().warning(e.toString());
|
getLogger().warning("Could not change permissions" +
|
||||||
|
" on userRoot directory. ");
|
||||||
}
|
}
|
||||||
userRootModTime = userRootModFile.lastModified();
|
getLogger().info("Created user preferences directory.");
|
||||||
return null;
|
} else {
|
||||||
|
getLogger().warning("Couldn't create user preferences" +
|
||||||
|
" directory. User preferences are unusable.");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
isUserRootWritable = userRootDir.canWrite();
|
||||||
|
String USER_NAME = System.getProperty("user.name");
|
||||||
|
userLockFile = new File(userRootDir,".user.lock." + USER_NAME);
|
||||||
|
userRootModFile = new File (userRootDir,
|
||||||
|
".userRootModFile." + USER_NAME);
|
||||||
|
if (!userRootModFile.exists()) {
|
||||||
|
try {
|
||||||
|
// create if does not exist.
|
||||||
|
userRootModFile.createNewFile();
|
||||||
|
// Only user can read/write userRootModFile.
|
||||||
|
int result = chmod(userRootModFile.getCanonicalPath(),
|
||||||
|
USER_READ_WRITE);
|
||||||
|
if (result != 0)
|
||||||
|
getLogger().warning("Problem creating userRoot " +
|
||||||
|
"mod file. Chmod failed on " +
|
||||||
|
userRootModFile.getCanonicalPath() +
|
||||||
|
" Unix error code " + result);
|
||||||
|
} catch (IOException e) {
|
||||||
|
getLogger().warning(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userRootModTime = userRootModFile.lastModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -185,58 +172,54 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static void setupSystemRoot() {
|
private static void setupSystemRoot() {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
String systemPrefsDirName =
|
||||||
public Void run() {
|
System.getProperty("java.util.prefs.systemRoot", "/etc/.java");
|
||||||
String systemPrefsDirName =
|
systemRootDir =
|
||||||
System.getProperty("java.util.prefs.systemRoot","/etc/.java");
|
new File(systemPrefsDirName, ".systemPrefs");
|
||||||
systemRootDir =
|
// Attempt to create root dir if it does not yet exist.
|
||||||
new File(systemPrefsDirName, ".systemPrefs");
|
if (!systemRootDir.exists()) {
|
||||||
// Attempt to create root dir if it does not yet exist.
|
// system root does not exist in /etc/.java
|
||||||
if (!systemRootDir.exists()) {
|
// Switching to java.home
|
||||||
// system root does not exist in /etc/.java
|
systemRootDir =
|
||||||
// Switching to java.home
|
new File(System.getProperty("java.home"),
|
||||||
systemRootDir =
|
".systemPrefs");
|
||||||
new File(System.getProperty("java.home"),
|
if (!systemRootDir.exists()) {
|
||||||
".systemPrefs");
|
if (systemRootDir.mkdirs()) {
|
||||||
if (!systemRootDir.exists()) {
|
getLogger().info(
|
||||||
if (systemRootDir.mkdirs()) {
|
"Created system preferences directory "
|
||||||
getLogger().info(
|
+ "in java.home.");
|
||||||
"Created system preferences directory "
|
try {
|
||||||
+ "in java.home.");
|
chmod(systemRootDir.getCanonicalPath(),
|
||||||
try {
|
USER_RWX_ALL_RX);
|
||||||
chmod(systemRootDir.getCanonicalPath(),
|
} catch (IOException e) {
|
||||||
USER_RWX_ALL_RX);
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getLogger().warning("Could not create "
|
|
||||||
+ "system preferences directory. System "
|
|
||||||
+ "preferences are unusable.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
getLogger().warning("Could not create "
|
||||||
|
+ "system preferences directory. System "
|
||||||
|
+ "preferences are unusable.");
|
||||||
}
|
}
|
||||||
isSystemRootWritable = systemRootDir.canWrite();
|
|
||||||
systemLockFile = new File(systemRootDir, ".system.lock");
|
|
||||||
systemRootModFile =
|
|
||||||
new File (systemRootDir,".systemRootModFile");
|
|
||||||
if (!systemRootModFile.exists() && isSystemRootWritable)
|
|
||||||
try {
|
|
||||||
// create if does not exist.
|
|
||||||
systemRootModFile.createNewFile();
|
|
||||||
int result = chmod(systemRootModFile.getCanonicalPath(),
|
|
||||||
USER_RW_ALL_READ);
|
|
||||||
if (result !=0)
|
|
||||||
getLogger().warning("Chmod failed on " +
|
|
||||||
systemRootModFile.getCanonicalPath() +
|
|
||||||
" Unix error code " + result);
|
|
||||||
} catch (IOException e) { getLogger().warning(e.toString());
|
|
||||||
}
|
|
||||||
systemRootModTime = systemRootModFile.lastModified();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
isSystemRootWritable = systemRootDir.canWrite();
|
||||||
|
systemLockFile = new File(systemRootDir, ".system.lock");
|
||||||
|
systemRootModFile = new File (systemRootDir, ".systemRootModFile");
|
||||||
|
if (!systemRootModFile.exists() && isSystemRootWritable) {
|
||||||
|
try {
|
||||||
|
// create if does not exist.
|
||||||
|
systemRootModFile.createNewFile();
|
||||||
|
int result = chmod(systemRootModFile.getCanonicalPath(),
|
||||||
|
USER_RW_ALL_READ);
|
||||||
|
if (result != 0) {
|
||||||
|
getLogger().warning("Chmod failed on " +
|
||||||
|
systemRootModFile.getCanonicalPath() +
|
||||||
|
" Unix error code " + result);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
getLogger().warning(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
systemRootModTime = systemRootModFile.lastModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -456,7 +439,6 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
addShutdownHook();
|
addShutdownHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static void addShutdownHook() {
|
private static void addShutdownHook() {
|
||||||
// Add periodic timer task to periodically sync cached prefs
|
// Add periodic timer task to periodically sync cached prefs
|
||||||
syncTimer.schedule(new TimerTask() {
|
syncTimer.schedule(new TimerTask() {
|
||||||
@ -466,16 +448,11 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
}, SYNC_INTERVAL*1000, SYNC_INTERVAL*1000);
|
}, SYNC_INTERVAL*1000, SYNC_INTERVAL*1000);
|
||||||
|
|
||||||
// Add shutdown hook to flush cached prefs on normal termination
|
// Add shutdown hook to flush cached prefs on normal termination
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
Runtime.getRuntime().addShutdownHook(
|
||||||
public Void run() {
|
new Thread(null, null, "Sync Timer Thread", 0, false) {
|
||||||
Runtime.getRuntime().addShutdownHook(
|
public void run() {
|
||||||
new Thread(null, null, "Sync Timer Thread", 0, false) {
|
syncTimer.cancel();
|
||||||
public void run() {
|
syncWorld();
|
||||||
syncTimer.cancel();
|
|
||||||
syncWorld();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -526,19 +503,13 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
* parent node and name. This constructor, called from childSpi,
|
* parent node and name. This constructor, called from childSpi,
|
||||||
* is used to make every node except for the two //roots.
|
* is used to make every node except for the two //roots.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private FileSystemPreferences(FileSystemPreferences parent, String name) {
|
private FileSystemPreferences(FileSystemPreferences parent, String name) {
|
||||||
super(parent, name);
|
super(parent, name);
|
||||||
isUserNode = parent.isUserNode;
|
isUserNode = parent.isUserNode;
|
||||||
dir = new File(parent.dir, dirName(name));
|
dir = new File(parent.dir, dirName(name));
|
||||||
prefsFile = new File(dir, "prefs.xml");
|
prefsFile = new File(dir, "prefs.xml");
|
||||||
tmpFile = new File(dir, "prefs.tmp");
|
tmpFile = new File(dir, "prefs.tmp");
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
newNode = !dir.exists();
|
||||||
public Void run() {
|
|
||||||
newNode = !dir.exists();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (newNode) {
|
if (newNode) {
|
||||||
// These 2 things guarantee node will get written at next flush/sync
|
// These 2 things guarantee node will get written at next flush/sync
|
||||||
prefsCache = new TreeMap<>();
|
prefsCache = new TreeMap<>();
|
||||||
@ -596,43 +567,32 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
* fails, a BackingStoreException is thrown and both prefsCache and
|
* fails, a BackingStoreException is thrown and both prefsCache and
|
||||||
* lastSyncTime are unaffected by the call.
|
* lastSyncTime are unaffected by the call.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private void loadCache() throws BackingStoreException {
|
private void loadCache() throws BackingStoreException {
|
||||||
|
Map<String, String> m = new TreeMap<>();
|
||||||
|
long newLastSyncTime = 0;
|
||||||
try {
|
try {
|
||||||
AccessController.doPrivileged(
|
newLastSyncTime = prefsFile.lastModified();
|
||||||
new PrivilegedExceptionAction<Void>() {
|
try (FileInputStream fis = new FileInputStream(prefsFile)) {
|
||||||
public Void run() throws BackingStoreException {
|
XmlSupport.importMap(fis, m);
|
||||||
Map<String, String> m = new TreeMap<>();
|
}
|
||||||
long newLastSyncTime = 0;
|
} catch(Exception e) {
|
||||||
try {
|
if (e instanceof InvalidPreferencesFormatException) {
|
||||||
newLastSyncTime = prefsFile.lastModified();
|
getLogger().warning("Invalid preferences format in "
|
||||||
try (FileInputStream fis = new FileInputStream(prefsFile)) {
|
+ prefsFile.getPath());
|
||||||
XmlSupport.importMap(fis, m);
|
prefsFile.renameTo( new File(
|
||||||
}
|
prefsFile.getParentFile(),
|
||||||
} catch(Exception e) {
|
"IncorrectFormatPrefs.xml"));
|
||||||
if (e instanceof InvalidPreferencesFormatException) {
|
m = new TreeMap<>();
|
||||||
getLogger().warning("Invalid preferences format in "
|
} else if (e instanceof FileNotFoundException) {
|
||||||
+ prefsFile.getPath());
|
getLogger().warning("Prefs file removed in background "
|
||||||
prefsFile.renameTo( new File(
|
+ prefsFile.getPath());
|
||||||
prefsFile.getParentFile(),
|
} else {
|
||||||
"IncorrectFormatPrefs.xml"));
|
throw new BackingStoreException(e);
|
||||||
m = new TreeMap<>();
|
}
|
||||||
} else if (e instanceof FileNotFoundException) {
|
|
||||||
getLogger().warning("Prefs file removed in background "
|
|
||||||
+ prefsFile.getPath());
|
|
||||||
} else {
|
|
||||||
throw new BackingStoreException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Attempt succeeded; update state
|
|
||||||
prefsCache = m;
|
|
||||||
lastSyncTime = newLastSyncTime;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
throw (BackingStoreException) e.getException();
|
|
||||||
}
|
}
|
||||||
|
// Attempt succeeded; update state
|
||||||
|
prefsCache = m;
|
||||||
|
lastSyncTime = newLastSyncTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -644,32 +604,21 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
* and lastSyncTime will be unaffected by this call. This call will
|
* and lastSyncTime will be unaffected by this call. This call will
|
||||||
* NEVER leave prefsFile in a corrupt state.
|
* NEVER leave prefsFile in a corrupt state.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private void writeBackCache() throws BackingStoreException {
|
private void writeBackCache() throws BackingStoreException {
|
||||||
try {
|
try {
|
||||||
AccessController.doPrivileged(
|
if (!dir.exists() && !dir.mkdirs())
|
||||||
new PrivilegedExceptionAction<Void>() {
|
throw new BackingStoreException(dir +
|
||||||
public Void run() throws BackingStoreException {
|
" create failed.");
|
||||||
try {
|
try (FileOutputStream fos = new FileOutputStream(tmpFile)) {
|
||||||
if (!dir.exists() && !dir.mkdirs())
|
XmlSupport.exportMap(fos, prefsCache);
|
||||||
throw new BackingStoreException(dir +
|
}
|
||||||
" create failed.");
|
if (!tmpFile.renameTo(prefsFile))
|
||||||
try (FileOutputStream fos = new FileOutputStream(tmpFile)) {
|
throw new BackingStoreException("Can't rename " +
|
||||||
XmlSupport.exportMap(fos, prefsCache);
|
tmpFile + " to " + prefsFile);
|
||||||
}
|
} catch(BackingStoreException e) {
|
||||||
if (!tmpFile.renameTo(prefsFile))
|
throw e;
|
||||||
throw new BackingStoreException("Can't rename " +
|
} catch(Exception e) {
|
||||||
tmpFile + " to " + prefsFile);
|
throw new BackingStoreException(e);
|
||||||
} catch(Exception e) {
|
|
||||||
if (e instanceof BackingStoreException)
|
|
||||||
throw (BackingStoreException)e;
|
|
||||||
throw new BackingStoreException(e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
throw (BackingStoreException) e.getException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,21 +627,15 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
return prefsCache.keySet().toArray(new String[prefsCache.size()]);
|
return prefsCache.keySet().toArray(new String[prefsCache.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
protected String[] childrenNamesSpi() {
|
protected String[] childrenNamesSpi() {
|
||||||
return AccessController.doPrivileged(
|
List<String> result = new ArrayList<>();
|
||||||
new PrivilegedAction<String[]>() {
|
File[] dirContents = dir.listFiles();
|
||||||
public String[] run() {
|
if (dirContents != null) {
|
||||||
List<String> result = new ArrayList<>();
|
for (int i = 0; i < dirContents.length; i++)
|
||||||
File[] dirContents = dir.listFiles();
|
if (dirContents[i].isDirectory())
|
||||||
if (dirContents != null) {
|
result.add(nodeName(dirContents[i].getName()));
|
||||||
for (int i = 0; i < dirContents.length; i++)
|
}
|
||||||
if (dirContents[i].isDirectory())
|
return result.toArray(EMPTY_STRING_ARRAY);
|
||||||
result.add(nodeName(dirContents[i].getName()));
|
|
||||||
}
|
|
||||||
return result.toArray(EMPTY_STRING_ARRAY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||||
@ -717,42 +660,30 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
/**
|
/**
|
||||||
* Called with file lock held (in addition to node locks).
|
* Called with file lock held (in addition to node locks).
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
protected void removeNodeSpi() throws BackingStoreException {
|
protected void removeNodeSpi() throws BackingStoreException {
|
||||||
try {
|
if (changeLog.contains(nodeCreate)) {
|
||||||
AccessController.doPrivileged(
|
changeLog.remove(nodeCreate);
|
||||||
new PrivilegedExceptionAction<Void>() {
|
nodeCreate = null;
|
||||||
public Void run() throws BackingStoreException {
|
return;
|
||||||
if (changeLog.contains(nodeCreate)) {
|
|
||||||
changeLog.remove(nodeCreate);
|
|
||||||
nodeCreate = null;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!dir.exists())
|
|
||||||
return null;
|
|
||||||
prefsFile.delete();
|
|
||||||
tmpFile.delete();
|
|
||||||
// dir should be empty now. If it's not, empty it
|
|
||||||
File[] junk = dir.listFiles();
|
|
||||||
if (junk.length != 0) {
|
|
||||||
getLogger().warning(
|
|
||||||
"Found extraneous files when removing node: "
|
|
||||||
+ Arrays.asList(junk));
|
|
||||||
for (int i=0; i<junk.length; i++)
|
|
||||||
junk[i].delete();
|
|
||||||
}
|
|
||||||
if (!dir.delete())
|
|
||||||
throw new BackingStoreException("Couldn't delete dir: "
|
|
||||||
+ dir);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
throw (BackingStoreException) e.getException();
|
|
||||||
}
|
}
|
||||||
|
if (!dir.exists())
|
||||||
|
return;
|
||||||
|
prefsFile.delete();
|
||||||
|
tmpFile.delete();
|
||||||
|
// dir should be empty now. If it's not, empty it
|
||||||
|
File[] junk = dir.listFiles();
|
||||||
|
if (junk.length != 0) {
|
||||||
|
getLogger().warning(
|
||||||
|
"Found extraneous files when removing node: "
|
||||||
|
+ Arrays.asList(junk));
|
||||||
|
for (int i=0; i<junk.length; i++)
|
||||||
|
junk[i].delete();
|
||||||
|
}
|
||||||
|
if (!dir.delete())
|
||||||
|
throw new BackingStoreException("Couldn't delete dir: "
|
||||||
|
+ dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
public synchronized void sync() throws BackingStoreException {
|
public synchronized void sync() throws BackingStoreException {
|
||||||
boolean userNode = isUserNode();
|
boolean userNode = isUserNode();
|
||||||
boolean shared;
|
boolean shared;
|
||||||
@ -765,58 +696,34 @@ class FileSystemPreferences extends AbstractPreferences {
|
|||||||
shared = !isSystemRootWritable;
|
shared = !isSystemRootWritable;
|
||||||
}
|
}
|
||||||
synchronized (isUserNode()? userLockFile:systemLockFile) {
|
synchronized (isUserNode()? userLockFile:systemLockFile) {
|
||||||
if (!lockFile(shared))
|
if (!lockFile(shared)) {
|
||||||
throw(new BackingStoreException("Couldn't get file lock."));
|
throw (new BackingStoreException("Couldn't get file lock."));
|
||||||
final Long newModTime =
|
}
|
||||||
AccessController.doPrivileged(
|
long nmt;
|
||||||
new PrivilegedAction<Long>() {
|
if (isUserNode()) {
|
||||||
public Long run() {
|
nmt = userRootModFile.lastModified();
|
||||||
long nmt;
|
isUserRootModified = userRootModTime == nmt;
|
||||||
if (isUserNode()) {
|
} else {
|
||||||
nmt = userRootModFile.lastModified();
|
nmt = systemRootModFile.lastModified();
|
||||||
isUserRootModified = userRootModTime == nmt;
|
isSystemRootModified = systemRootModTime == nmt;
|
||||||
} else {
|
}
|
||||||
nmt = systemRootModFile.lastModified();
|
final long newModTime = nmt;
|
||||||
isSystemRootModified = systemRootModTime == nmt;
|
|
||||||
}
|
|
||||||
return nmt;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
super.sync();
|
super.sync();
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
if (isUserNode()) {
|
||||||
public Void run() {
|
userRootModTime = newModTime + 1000;
|
||||||
if (isUserNode()) {
|
userRootModFile.setLastModified(userRootModTime);
|
||||||
userRootModTime = newModTime.longValue() + 1000;
|
} else {
|
||||||
userRootModFile.setLastModified(userRootModTime);
|
systemRootModTime = newModTime + 1000;
|
||||||
} else {
|
systemRootModFile.setLastModified(systemRootModTime);
|
||||||
systemRootModTime = newModTime.longValue() + 1000;
|
}
|
||||||
systemRootModFile.setLastModified(systemRootModTime);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} finally {
|
} finally {
|
||||||
unlockFile();
|
unlockFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
protected void syncSpi() throws BackingStoreException {
|
protected void syncSpi() throws BackingStoreException {
|
||||||
try {
|
|
||||||
AccessController.doPrivileged(
|
|
||||||
new PrivilegedExceptionAction<Void>() {
|
|
||||||
public Void run() throws BackingStoreException {
|
|
||||||
syncSpiPrivileged();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
throw (BackingStoreException) e.getException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void syncSpiPrivileged() throws BackingStoreException {
|
|
||||||
if (isRemoved())
|
if (isRemoved())
|
||||||
throw new IllegalStateException("Node has been removed");
|
throw new IllegalStateException("Node has been removed");
|
||||||
if (prefsCache == null)
|
if (prefsCache == null)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,8 +27,6 @@ package java.util.prefs;
|
|||||||
|
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
|
|
||||||
import sun.util.logging.PlatformLogger;
|
import sun.util.logging.PlatformLogger;
|
||||||
|
|
||||||
@ -50,13 +48,9 @@ class WindowsPreferences extends AbstractPreferences {
|
|||||||
loadPrefsLib();
|
loadPrefsLib();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"removal", "restricted"})
|
@SuppressWarnings("restricted")
|
||||||
private static void loadPrefsLib() {
|
private static void loadPrefsLib() {
|
||||||
PrivilegedAction<Void> load = () -> {
|
System.loadLibrary("prefs");
|
||||||
System.loadLibrary("prefs");
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
AccessController.doPrivileged(load);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user