Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java
38918 views
1
/*
2
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.util.prefs;
27
28
import java.util.Objects;
29
30
class MacOSXPreferences extends AbstractPreferences {
31
// fixme need security checks?
32
33
// CF preferences file name for Java nodes with short names
34
// This value is also in MacOSXPreferencesFile.c
35
private static final String defaultAppName = "com.apple.java.util.prefs";
36
37
// true if this node is a child of userRoot or is userRoot
38
private final boolean isUser;
39
40
// true if this node is userRoot or systemRoot
41
private final boolean isRoot;
42
43
// CF's storage location for this node and its keys
44
private final MacOSXPreferencesFile file;
45
46
// absolutePath() + "/"
47
private final String path;
48
49
// User root and system root nodes
50
private static volatile MacOSXPreferences userRoot;
51
private static volatile MacOSXPreferences systemRoot;
52
53
54
// Returns user root node, creating it if necessary.
55
// Called by MacOSXPreferencesFactory
56
static Preferences getUserRoot() {
57
MacOSXPreferences root = userRoot;
58
if (root == null) {
59
synchronized (MacOSXPreferences.class) {
60
root = userRoot;
61
if (root == null) {
62
userRoot = root = new MacOSXPreferences(true);
63
}
64
}
65
}
66
return root;
67
}
68
69
70
// Returns system root node, creating it if necessary.
71
// Called by MacOSXPreferencesFactory
72
static Preferences getSystemRoot() {
73
MacOSXPreferences root = systemRoot;
74
if (root == null) {
75
synchronized (MacOSXPreferences.class) {
76
root = systemRoot;
77
if (root == null) {
78
systemRoot = root = new MacOSXPreferences(false);
79
}
80
}
81
}
82
return root;
83
}
84
85
86
// Create a new root node. Called by getUserRoot() and getSystemRoot()
87
// Synchronization is provided by the caller.
88
private MacOSXPreferences(boolean newIsUser) {
89
this(null, "", false, true, newIsUser);
90
}
91
92
93
// Create a new non-root node with the given parent.
94
// Called by childSpi().
95
private MacOSXPreferences(MacOSXPreferences parent, String name) {
96
this(parent, name, false, false, false);
97
}
98
99
private MacOSXPreferences(MacOSXPreferences parent, String name,
100
boolean isNew)
101
{
102
this(parent, name, isNew, false, false);
103
}
104
105
private MacOSXPreferences(MacOSXPreferences parent, String name,
106
boolean isNew, boolean isRoot, boolean isUser)
107
{
108
super(parent, name);
109
this.isRoot = isRoot;
110
if (isRoot)
111
this.isUser = isUser;
112
else
113
this.isUser = isUserNode();
114
path = isRoot ? absolutePath() : absolutePath() + "/";
115
file = cfFileForNode(this.isUser);
116
if (isNew)
117
newNode = isNew;
118
else
119
newNode = file.addNode(path);
120
}
121
122
// Create and return the MacOSXPreferencesFile for this node.
123
// Does not write anything to the file.
124
private MacOSXPreferencesFile cfFileForNode(boolean isUser)
125
{
126
String name = path;
127
// /one/two/three/four/five/
128
// The fourth slash is the end of the first three components.
129
// If there is no fourth slash, the name has fewer than 3 components
130
int componentCount = 0;
131
int pos = -1;
132
for (int i = 0; i < 4; i++) {
133
pos = name.indexOf('/', pos+1);
134
if (pos == -1) break;
135
}
136
137
if (pos == -1) {
138
// fewer than three components - use default name
139
name = defaultAppName;
140
} else {
141
// truncate to three components, no leading or trailing '/'
142
// replace '/' with '.' to make filesystem happy
143
// convert to all lowercase to survive on HFS+
144
name = name.substring(1, pos);
145
name = name.replace('/', '.');
146
name = name.toLowerCase();
147
}
148
149
return MacOSXPreferencesFile.getFile(name, isUser);
150
}
151
152
153
// AbstractPreferences implementation
154
@Override
155
protected void putSpi(String key, String value)
156
{
157
file.addKeyToNode(path, key, value);
158
}
159
160
// AbstractPreferences implementation
161
@Override
162
protected String getSpi(String key)
163
{
164
return file.getKeyFromNode(path, key);
165
}
166
167
// AbstractPreferences implementation
168
@Override
169
protected void removeSpi(String key)
170
{
171
Objects.requireNonNull(key, "Specified key cannot be null");
172
file.removeKeyFromNode(path, key);
173
}
174
175
176
// AbstractPreferences implementation
177
@Override
178
protected void removeNodeSpi()
179
throws BackingStoreException
180
{
181
// Disallow flush or sync between these two operations
182
// (they may be manipulating two different files)
183
synchronized(MacOSXPreferencesFile.class) {
184
((MacOSXPreferences)parent()).removeChild(name());
185
file.removeNode(path);
186
}
187
}
188
189
// Erase knowledge about a child of this node. Called by removeNodeSpi.
190
private void removeChild(String child)
191
{
192
file.removeChildFromNode(path, child);
193
}
194
195
196
// AbstractPreferences implementation
197
@Override
198
protected String[] childrenNamesSpi()
199
throws BackingStoreException
200
{
201
String[] result = file.getChildrenForNode(path);
202
if (result == null) throw new BackingStoreException("Couldn't get list of children for node '" + path + "'");
203
return result;
204
}
205
206
// AbstractPreferences implementation
207
@Override
208
protected String[] keysSpi()
209
throws BackingStoreException
210
{
211
String[] result = file.getKeysForNode(path);
212
if (result == null) throw new BackingStoreException("Couldn't get list of keys for node '" + path + "'");
213
return result;
214
}
215
216
// AbstractPreferences implementation
217
@Override
218
protected AbstractPreferences childSpi(String name)
219
{
220
// Add to parent's child list here and disallow sync
221
// because parent and child might be in different files.
222
synchronized(MacOSXPreferencesFile.class) {
223
boolean isNew = file.addChildToNode(path, name);
224
return new MacOSXPreferences(this, name, isNew);
225
}
226
}
227
228
// AbstractPreferences override
229
@Override
230
public void flush()
231
throws BackingStoreException
232
{
233
// Flush should *not* check for removal, unlike sync, but should
234
// prevent simultaneous removal.
235
synchronized(lock) {
236
if (isUser) {
237
if (!MacOSXPreferencesFile.flushUser()) {
238
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
239
}
240
} else {
241
if (!MacOSXPreferencesFile.flushWorld()) {
242
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
243
}
244
}
245
}
246
}
247
248
// AbstractPreferences implementation
249
@Override
250
protected void flushSpi()
251
throws BackingStoreException
252
{
253
// nothing here - overridden flush() doesn't call this
254
}
255
256
// AbstractPreferences override
257
@Override
258
public void sync()
259
throws BackingStoreException
260
{
261
synchronized(lock) {
262
if (isRemoved())
263
throw new IllegalStateException("Node has been removed");
264
// fixme! overkill
265
if (isUser) {
266
if (!MacOSXPreferencesFile.syncUser()) {
267
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
268
}
269
} else {
270
if (!MacOSXPreferencesFile.syncWorld()) {
271
throw new BackingStoreException("Synchronization failed for node '" + path + "'");
272
}
273
}
274
}
275
}
276
277
// AbstractPreferences implementation
278
@Override
279
protected void syncSpi()
280
throws BackingStoreException
281
{
282
// nothing here - overridden sync() doesn't call this
283
}
284
}
285
286
287