66 * 1. All the selective locale data are in jdk.localedata module
67 * 2. Their package names are constructed by appending ".ext" to
68 * the corresponding ones in java.base module.
69 * 3. Available locales string in LocaleDataMetaInfo class should
70 * start with at least one white space character, e.g., " ar ar-EG ..."
71 * ^
72 */
73 public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePrevisitor {
74
75 public static final String NAME = "include-locales";
76 private static final String MODULENAME = "jdk.localedata";
77 private static final Set<String> LOCALEDATA_PACKAGES = Set.of(
78 "sun.text.resources.cldr.ext",
79 "sun.text.resources.ext",
80 "sun.util.resources.cldr.ext",
81 "sun.util.resources.cldr.provider",
82 "sun.util.resources.ext",
83 "sun.util.resources.provider");
84 private static final String METAINFONAME = "LocaleDataMetaInfo";
85 private static final String META_FILES =
86 "*module-info.class," +
87 "*LocaleDataProvider.class," +
88 "*" + METAINFONAME + ".class,";
89 private static final String INCLUDE_LOCALE_FILES =
90 "*sun/text/resources/ext/[^\\/]+_%%.class," +
91 "*sun/util/resources/ext/[^\\/]+_%%.class," +
92 "*sun/text/resources/cldr/ext/[^\\/]+_%%.class," +
93 "*sun/util/resources/cldr/ext/[^\\/]+_%%.class,";
94 private Predicate<String> predicate;
95 private String userParam;
96 private List<Locale.LanguageRange> priorityList;
97 private List<Locale> available;
98 private List<String> filtered;
99
100 // Special COMPAT provider locales
101 private static final String jaJPJPTag = "ja-JP-JP";
102 private static final String noNONYTag = "no-NO-NY";
103 private static final String thTHTHTag = "th-TH-TH";
104 private static final Locale jaJPJP = new Locale("ja", "JP", "JP");
105 private static final Locale noNONY = new Locale("no", "NO", "NY");
106 private static final Locale thTHTH = new Locale("th", "TH", "TH");
107
108 @Override
109 public String getName() {
110 return NAME;
111 }
112
113 @Override
236 break;
237 }
238 }
239
240 final String lang = pTag;
241
242 // Add possible special locales of the COMPAT provider
243 files += Set.of(jaJPJPTag, noNONYTag, thTHTHTag).stream()
244 .filter(stag -> lang.equals(stag.substring(0,2)))
245 .map(t -> INCLUDE_LOCALE_FILES.replaceAll("%%", t.replaceAll("-", "_")))
246 .collect(Collectors.joining(","));
247
248 // Add possible UN.M49 files (unconditional for now) for each language
249 files += INCLUDE_LOCALE_FILES.replaceAll("%%", lang + "_[0-9]{3}");
250 if (!isoSpecial.isEmpty()) {
251 files += INCLUDE_LOCALE_FILES.replaceAll("%%", isoSpecial + "_[0-9]{3}");
252 }
253
254 // Add Thai BreakIterator related data files
255 if (lang.equals("th")) {
256 files += "*sun/text/resources/thai_dict," +
257 "*sun/text/resources/[^\\/]+BreakIteratorData_th,";
258 }
259
260 // Add Taiwan resource bundles for Hong Kong
261 if (tag.startsWith("zh-HK")) {
262 files += INCLUDE_LOCALE_FILES.replaceAll("%%", "zh_TW");
263 }
264
265 return files;
266 }
267
268 private boolean stripUnsupportedLocales(byte[] bytes, ClassReader cr) {
269 char[] buf = new char[cr.getMaxStringLength()];
270 boolean[] modified = new boolean[1];
271
272 IntStream.range(1, cr.getItemCount())
273 .map(item -> cr.getItem(item))
274 .forEach(itemIndex -> {
275 if (bytes[itemIndex - 1] == 1 && // UTF-8
276 bytes[itemIndex + 2] == (byte)' ') { // fast check for leading space
277 int length = cr.readUnsignedShort(itemIndex);
|
66 * 1. All the selective locale data are in jdk.localedata module
67 * 2. Their package names are constructed by appending ".ext" to
68 * the corresponding ones in java.base module.
69 * 3. Available locales string in LocaleDataMetaInfo class should
70 * start with at least one white space character, e.g., " ar ar-EG ..."
71 * ^
72 */
73 public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePrevisitor {
74
75 public static final String NAME = "include-locales";
76 private static final String MODULENAME = "jdk.localedata";
77 private static final Set<String> LOCALEDATA_PACKAGES = Set.of(
78 "sun.text.resources.cldr.ext",
79 "sun.text.resources.ext",
80 "sun.util.resources.cldr.ext",
81 "sun.util.resources.cldr.provider",
82 "sun.util.resources.ext",
83 "sun.util.resources.provider");
84 private static final String METAINFONAME = "LocaleDataMetaInfo";
85 private static final String META_FILES =
86 "regex:.+module-info.class," +
87 "regex:.+LocaleDataProvider.class," +
88 "regex:.+" + METAINFONAME + ".class,";
89 private static final String INCLUDE_LOCALE_FILES =
90 "regex:.+sun/text/resources/ext/[^_]+_%%.class," +
91 "regex:.+sun/util/resources/ext/[^_]+_%%.class," +
92 "regex:.+sun/text/resources/cldr/ext/[^_]+_%%.class," +
93 "regex:.+sun/util/resources/cldr/ext/[^_]+_%%.class,";
94 private Predicate<String> predicate;
95 private String userParam;
96 private List<Locale.LanguageRange> priorityList;
97 private List<Locale> available;
98 private List<String> filtered;
99
100 // Special COMPAT provider locales
101 private static final String jaJPJPTag = "ja-JP-JP";
102 private static final String noNONYTag = "no-NO-NY";
103 private static final String thTHTHTag = "th-TH-TH";
104 private static final Locale jaJPJP = new Locale("ja", "JP", "JP");
105 private static final Locale noNONY = new Locale("no", "NO", "NY");
106 private static final Locale thTHTH = new Locale("th", "TH", "TH");
107
108 @Override
109 public String getName() {
110 return NAME;
111 }
112
113 @Override
236 break;
237 }
238 }
239
240 final String lang = pTag;
241
242 // Add possible special locales of the COMPAT provider
243 files += Set.of(jaJPJPTag, noNONYTag, thTHTHTag).stream()
244 .filter(stag -> lang.equals(stag.substring(0,2)))
245 .map(t -> INCLUDE_LOCALE_FILES.replaceAll("%%", t.replaceAll("-", "_")))
246 .collect(Collectors.joining(","));
247
248 // Add possible UN.M49 files (unconditional for now) for each language
249 files += INCLUDE_LOCALE_FILES.replaceAll("%%", lang + "_[0-9]{3}");
250 if (!isoSpecial.isEmpty()) {
251 files += INCLUDE_LOCALE_FILES.replaceAll("%%", isoSpecial + "_[0-9]{3}");
252 }
253
254 // Add Thai BreakIterator related data files
255 if (lang.equals("th")) {
256 files += "regex:.+sun/text/resources/thai_dict," +
257 "regex:.+sun/text/resources/[^_]+BreakIteratorData_th,";
258 }
259
260 // Add Taiwan resource bundles for Hong Kong
261 if (tag.startsWith("zh-HK")) {
262 files += INCLUDE_LOCALE_FILES.replaceAll("%%", "zh_TW");
263 }
264
265 return files;
266 }
267
268 private boolean stripUnsupportedLocales(byte[] bytes, ClassReader cr) {
269 char[] buf = new char[cr.getMaxStringLength()];
270 boolean[] modified = new boolean[1];
271
272 IntStream.range(1, cr.getItemCount())
273 .map(item -> cr.getItem(item))
274 .forEach(itemIndex -> {
275 if (bytes[itemIndex - 1] == 1 && // UTF-8
276 bytes[itemIndex + 2] == (byte)' ') { // fast check for leading space
277 int length = cr.readUnsignedShort(itemIndex);
|