Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/util/Resources/NewResourcesNames.java
38853 views
1
/*
2
* Copyright (c) 2010, 2012, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import java.io.BufferedReader;
25
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.FileOutputStream;
28
import java.io.InputStreamReader;
29
import java.io.PrintWriter;
30
import java.util.HashMap;
31
import java.util.HashSet;
32
import java.util.ListResourceBundle;
33
import java.util.Map;
34
import java.util.Set;
35
36
/**
37
* Prepares new key names for Resources.java.
38
* 6987827: security/util/Resources.java needs improvement
39
*
40
* Run inside jdk/src/share/classes:
41
*
42
* java NewResourcesNames $(
43
* for a in $(find com/sun/security sun/security javax/security -type f); do
44
* egrep -q '(ResourcesMgr.getString|rb.getString)' $a && echo $a
45
* done)
46
*
47
* Before running this tool, run the following two commands to make sure there
48
* are only these 2 types of calls into the resources:
49
* for a in `find com/sun/security sun/security javax/security -type f`; do
50
* cat $a | perl -ne 'print if /\bResourcesMgr\b/'; done |
51
* grep -v ResourcesMgr.getString
52
* for a in `find com/sun/security sun/security -type f`; do
53
* cat $a | perl -ne 'print if /\brb\b/'; done |
54
* grep -v rb.getString
55
*/
56
class NewResourcesNames {
57
58
// Max length of normalized names
59
static int MAXLEN = 127;
60
61
static String[] resources = {
62
"sun/security/tools/jarsigner/Resources.java",
63
"sun/security/tools/keytool/Resources.java",
64
"sun/security/tools/policytool/Resources.java",
65
"sun/security/util/Resources.java",
66
"sun/security/util/AuthResources.java",
67
};
68
69
public static void main(String[] args) throws Exception {
70
71
// Load all names inside resources files
72
Map<String,String> allnames = loadResources();
73
74
// Modify the callers. There are two patterns:
75
// 1. ResourcesMgr.getString("
76
// used by most JAAS codes
77
// 2. rb.getString("
78
// used by tools
79
Set<String> allfound = new HashSet<String>();
80
for (String arg: args) {
81
allfound.addAll(rewriteFile(arg, "ResourcesMgr.getString(\""));
82
allfound.addAll(rewriteFile(arg, "rb.getString(\""));
83
}
84
85
// Special case 1: KeyTool's enum definition of commands and options
86
allfound.addAll(keyToolEnums());
87
88
// Special case 2: PolicyFile called this 4 times
89
allfound.addAll(rewriteFile("sun/security/provider/PolicyFile.java",
90
"ResourcesMgr.getString(POLICY+\""));
91
92
// During the calls above, you can read sth like:
93
//
94
// Working on com/sun/security/auth/PolicyParser.java
95
// GOOD match is 17
96
//
97
// This means a " exists right after getString(. Sometimes you see
98
//
99
// Working on sun/security/tools/keytool/Main.java
100
// BAD!! pmatch != match: 212 != 209
101
// Working on sun/security/provider/PolicyFile.java
102
// BAD!! pmatch != match: 14 != 10
103
//
104
// which is mismatch. There are only two such special cases list above.
105
// For KeyTool, there are 3 calls for showing help. For PolicyTool, 3
106
// for name prefixed with POLICY. They are covered in the two special
107
// cases above.
108
109
// Names used but not defined. This is mostly error, except for
110
// special case 2 above. So it's OK to see 3 entries red here
111
if (!allnames.keySet().containsAll(allfound)) {
112
err("FATAL: Undefined names");
113
for (String name: allfound) {
114
if (!allnames.keySet().contains(name)) {
115
err(" " + name);
116
}
117
}
118
}
119
120
// Names defined but not used. Mostly this is old entries not removed.
121
// When soemone remove a line of code, he dares not remove the entry
122
// in case it's also used somewhere else.
123
if (!allfound.containsAll(allnames.keySet())) {
124
System.err.println("WARNING: Unused names");
125
for (String name: allnames.keySet()) {
126
if (!allfound.contains(name)) {
127
System.err.println(allnames.get(name));
128
System.err.println(" " + normalize(name));
129
System.err.println(" [" + name + "]");
130
}
131
}
132
}
133
}
134
135
136
/**
137
* Loads the three resources files. Saves names into a Map.
138
*/
139
private static Map<String,String> loadResources() throws Exception {
140
141
// Name vs Resource
142
Map<String,String> allnames = new HashMap<String,String>();
143
144
for (String f: resources) {
145
String clazz =
146
f.replace('/', '.').substring(0, f.length()-5);
147
148
Set<String> expected = loadClass(clazz);
149
Set<String> found = rewriteFile(f, "{\"");
150
151
// This is to check that word parsing is identical to Java thinks
152
if (!expected.equals(found)) {
153
throw new Exception("Expected and found do not match");
154
}
155
156
for (String name: found) {
157
allnames.put(name, f);
158
}
159
}
160
return allnames;
161
}
162
163
/**
164
* Special case treat for enums description in KeyTool
165
*/
166
private static Set<String> keyToolEnums() throws Exception {
167
168
Set<String> names = new HashSet<String>();
169
170
String file = "sun/security/tools/keytool/Main.java";
171
System.err.println("Working on " + file);
172
File origFile = new File(file);
173
File tmpFile = new File(file + ".tmp");
174
origFile.renameTo(tmpFile);
175
tmpFile.deleteOnExit();
176
177
BufferedReader br = new BufferedReader(
178
new InputStreamReader(new FileInputStream(tmpFile)));
179
PrintWriter out = new PrintWriter(new FileOutputStream(origFile));
180
181
int stage = 0; // 1. commands, 2. options, 3. finished
182
int match = 0;
183
184
while (true) {
185
String s = br.readLine();
186
if (s == null) {
187
break;
188
}
189
if (s.indexOf("enum Command") >= 0) stage = 1;
190
else if (s.indexOf("enum Option") >= 0) stage = 2;
191
else if (s.indexOf("private static final String JKS") >= 0) stage = 3;
192
193
if (stage == 1 || stage == 2) {
194
if (s.indexOf("(\"") >= 0) {
195
match++;
196
int p1, p2;
197
if (stage == 1) {
198
p1 = s.indexOf("\"");
199
p2 = s.indexOf("\"", p1+1);
200
} else {
201
p2 = s.lastIndexOf("\"");
202
p1 = s.lastIndexOf("\"", p2-1);
203
}
204
String name = s.substring(p1+1, p2);
205
names.add(name);
206
out.println(s.substring(0, p1+1) +
207
normalize(name) +
208
s.substring(p2));
209
} else {
210
out.println(s);
211
}
212
} else {
213
out.println(s);
214
}
215
}
216
br.close();
217
out.close();
218
System.err.println(" GOOD match is " + match);
219
return names;
220
}
221
222
/**
223
* Loads a resources using JRE and returns the names
224
*/
225
private static Set<String> loadClass(String clazz) throws Exception {
226
ListResourceBundle lrb =
227
(ListResourceBundle)Class.forName(clazz).newInstance();
228
Set<String> keys = lrb.keySet();
229
Map<String,String> newold = new HashMap<String,String>();
230
boolean dup = false;
231
// Check if normalize() creates dup entries. This is crucial.
232
for (String k: keys) {
233
String key = normalize(k);
234
if (newold.containsKey(key)) {
235
err("Dup found for " + key + ":");
236
err("["+newold.get(key)+"]");
237
err("["+k+"]");
238
dup = true;
239
}
240
newold.put(key, k);
241
}
242
if (dup) throw new Exception();
243
return keys;
244
}
245
246
/**
247
* Rewrites a file using a pattern. The name string should be right after
248
* the pattern. Note: pattern ignores whitespaces. Returns names found.
249
*/
250
private static Set<String> rewriteFile(String file, String pattern)
251
throws Exception {
252
253
System.err.println("Working on " + file);
254
Set<String> names = new HashSet<String>();
255
256
int plen = pattern.length();
257
int match = 0;
258
259
// The bare XXX.getString is also matched. Sometimes getString is
260
// called but does not use literal strings. This is harder to solve.
261
262
int pmatch = 0;
263
int pheadlen = plen - 2;
264
String phead = pattern.substring(0, plen-2);
265
266
// The non-whitespace chars read since, used to check for pattern
267
StringBuilder history = new StringBuilder();
268
int hlen = 0;
269
270
File origFile = new File(file);
271
File tmpFile = new File(file + ".tmp");
272
origFile.renameTo(tmpFile);
273
tmpFile.deleteOnExit();
274
275
FileInputStream fis = new FileInputStream(tmpFile);
276
FileOutputStream fos = new FileOutputStream(origFile);
277
278
while (true) {
279
int ch = fis.read();
280
if (ch < 0) break;
281
if (!Character.isWhitespace(ch)) {
282
history.append((char)ch);
283
hlen++;
284
if (pheadlen > 0 && hlen >= pheadlen &&
285
history.substring(hlen-pheadlen, hlen).equals(phead)) {
286
pmatch++;
287
}
288
}
289
290
if (hlen >= plen &&
291
history.substring(hlen-plen, hlen).equals(pattern)) {
292
match++;
293
history = new StringBuilder();
294
hlen = 0;
295
296
fos.write(ch);
297
298
// Save a name
299
StringBuilder sb = new StringBuilder();
300
// Save things after the second ". Maybe it's an end, maybe
301
// it's just literal string concatenation.
302
StringBuilder tail = new StringBuilder();
303
304
boolean in = true; // inside name string
305
while (true) {
306
int n = fis.read();
307
if (in) {
308
if (n == '\\') {
309
int second = fis.read();
310
switch (second) {
311
case 'n': sb.append('\n'); break;
312
case 'r': sb.append('\r'); break;
313
case 't': sb.append('\t'); break;
314
case '"': sb.append('"'); break;
315
default: throw new Exception(String.format(
316
"I don't know this escape: %s%c",
317
sb.toString(), second));
318
}
319
} else if (n == '"') {
320
in = false;
321
// Maybe string concat? say bytes until clear
322
tail = new StringBuilder();
323
tail.append('"');
324
} else {
325
sb.append((char)n);
326
}
327
} else {
328
tail.append((char)n);
329
if (n == '"') { // string concat, in again
330
in = true;
331
} else if (n == ',' || n == ')') { // real end
332
break;
333
} else if (Character.isWhitespace(n) || n == '+') {
334
// string concat
335
} else {
336
throw new Exception("Not a correct concat");
337
}
338
}
339
}
340
String s = sb.toString();
341
names.add(s);
342
fos.write(normalize(s).getBytes());
343
fos.write(tail.toString().getBytes());
344
} else {
345
fos.write(ch);
346
}
347
}
348
349
// Check pheadlen > 0. Don't want to mess with rewrite for resources
350
if (pheadlen > 0 && pmatch != match) {
351
err(" BAD!! pmatch != match: " + pmatch + " != " + match);
352
} else {
353
System.err.println(" GOOD match is " + match);
354
}
355
356
fis.close();
357
fos.close();
358
return names;
359
}
360
361
/**
362
* Normalize a string. Rules:
363
*
364
* 1. If all spacebar return "nSPACE", n is count
365
* 2. If consisting at least one alphanumeric:
366
* a. All alphanumeric remain
367
* b. All others in a row goes to a single ".", even if at head or tail
368
* 3. Otherwise:
369
* a. "****\n\n" to "STARNN", special case
370
* b. the English name if first char in *,.\n():'"
371
*
372
* Current observations show there's no dup, Hurray! Otherwise, add more
373
* special cases.
374
*/
375
private static String normalize(String s) throws Exception {
376
boolean needDot = false;
377
378
// All spacebar case
379
int n = 0;
380
for (char c: s.toCharArray()) {
381
if (c == ' ') n++;
382
else n = -10000;
383
}
384
if (n == 1) return "SPACE";
385
else if (n > 1) return "" + n + "SPACE";
386
387
StringBuilder sb = new StringBuilder();
388
int dotpos = -1;
389
for (int i=0; i<s.length(); i++) {
390
char c = s.charAt(i);
391
if (Character.isLetter(c) || Character.isDigit(c) ||
392
c == '{' || c == '}') {
393
if (needDot) {
394
// Rememeber the last dot, we want shorter form nice
395
if (sb.length() <= MAXLEN) dotpos = sb.length();
396
// "." only added when an alphanumeric is seen. This makes
397
// sure sb is empty when there's no alphanumerics at all
398
sb.append(".");
399
}
400
sb.append(c);
401
needDot = false;
402
} else {
403
needDot = true;
404
}
405
}
406
407
// No alphanemeric?
408
if (sb.length() == 0) {
409
if (s.contains("*") && s.contains("\n")) {
410
return "STARNN";
411
}
412
for (char c: s.toCharArray()) {
413
switch (c) {
414
case '*': return "STAR";
415
case ',': return "COMMA";
416
case '.': return "PERIOD";
417
case '\n': return "NEWLINE";
418
case '(': return "LPARAM";
419
case ')': return "RPARAM";
420
case ':': return "COLON";
421
case '\'': case '"': return "QUOTE";
422
}
423
}
424
throw new Exception("Unnamed char: [" + s + "]");
425
}
426
427
// tail "." only added when there are alphanumerics
428
if (needDot) sb.append('.');
429
String res = sb.toString();
430
if (res.length() > MAXLEN) {
431
if (dotpos < 0) throw new Exception("No dot all over? " + s);
432
return res.substring(0, dotpos);
433
} else {
434
return res;
435
}
436
}
437
438
private static void err(String string) {
439
System.out.println("\u001b[1;37;41m" + string + "\u001b[m");
440
}
441
}
442
443