8165804: Revisit the way of loading BreakIterator rules/dictionaries
Reviewed-by: naoto, peytoia, erikj
This commit is contained in:
parent
bf19611451
commit
6ce08d0985
@ -55,7 +55,6 @@ $(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_BASE, \
|
||||
$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
|
||||
SETUP := GENERATE_OLDBYTECODE, \
|
||||
SRC := $(JDK_TOPDIR)/src/jdk.localedata/share/classes, \
|
||||
INCLUDES := $(TEXT_PKG_LD), \
|
||||
INCLUDE_FILES := \
|
||||
$(TEXT_PKG_LD)/BreakIteratorRules_th.java \
|
||||
$(TEXT_PKG_LD)/BreakIteratorInfo_th.java, \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,15 +37,10 @@
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
package sun.text;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.MissingResourceException;
|
||||
import sun.text.CompactByteArray;
|
||||
import sun.text.SupplementaryCharacterData;
|
||||
@ -137,131 +132,90 @@ class BreakDictionary {
|
||||
// deserialization
|
||||
//=========================================================================
|
||||
|
||||
BreakDictionary(Module module, String dictionaryName)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
readDictionaryFile(module, dictionaryName);
|
||||
}
|
||||
|
||||
private void readDictionaryFile(final Module module, final String dictionaryName)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
BufferedInputStream in;
|
||||
BreakDictionary(String dictionaryName, byte[] dictionaryData) {
|
||||
try {
|
||||
PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
|
||||
String pathName = "jdk.localedata".equals(module.getName()) ?
|
||||
"sun/text/resources/ext/" :
|
||||
"sun/text/resources/";
|
||||
InputStream is = module.getResourceAsStream(pathName + dictionaryName);
|
||||
if (is == null) {
|
||||
// Try to load the file with "java.base" module instance. Assumption
|
||||
// here is that the fall back data files to be read should reside in
|
||||
// java.base.
|
||||
is = BreakDictionary.class.getModule().getResourceAsStream("sun/text/resources/" + dictionaryName);
|
||||
}
|
||||
|
||||
return new BufferedInputStream(is);
|
||||
};
|
||||
in = AccessController.doPrivileged(pa);
|
||||
}
|
||||
catch (PrivilegedActionException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
|
||||
byte[] buf = new byte[8];
|
||||
if (in.read(buf) != 8) {
|
||||
throw new MissingResourceException("Wrong data length",
|
||||
setupDictionary(dictionaryName, dictionaryData);
|
||||
} catch (BufferUnderflowException bue) {
|
||||
MissingResourceException e;
|
||||
e = new MissingResourceException("Corrupted dictionary data",
|
||||
dictionaryName, "");
|
||||
e.initCause(bue);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupDictionary(String dictionaryName, byte[] dictionaryData) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(dictionaryData);
|
||||
|
||||
// check version
|
||||
int version = RuleBasedBreakIterator.getInt(buf, 0);
|
||||
int version = bb.getInt();
|
||||
if (version != supportedVersion) {
|
||||
throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
|
||||
dictionaryName, "");
|
||||
}
|
||||
|
||||
// get data size
|
||||
int len = RuleBasedBreakIterator.getInt(buf, 4);
|
||||
buf = new byte[len];
|
||||
if (in.read(buf) != len) {
|
||||
throw new MissingResourceException("Wrong data length",
|
||||
// Check data size
|
||||
int len = bb.getInt();
|
||||
if (bb.position() + len != bb.limit()) {
|
||||
throw new MissingResourceException("Dictionary size is wrong: " + bb.limit(),
|
||||
dictionaryName, "");
|
||||
}
|
||||
|
||||
// close the stream
|
||||
in.close();
|
||||
|
||||
int l;
|
||||
int offset = 0;
|
||||
|
||||
// read in the column map for BMP characteres (this is serialized in
|
||||
// its internal form: an index array followed by a data array)
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
short[] temp = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
temp[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
}
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
byte[] temp2 = new byte[l];
|
||||
for (int i = 0; i < l; i++, offset++) {
|
||||
temp2[i] = buf[offset];
|
||||
len = bb.getInt();
|
||||
short[] temp = new short[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
temp[i] = bb.getShort();
|
||||
}
|
||||
len = bb.getInt();
|
||||
byte[] temp2 = new byte[len];
|
||||
bb.get(temp2);
|
||||
columnMap = new CompactByteArray(temp, temp2);
|
||||
|
||||
// read in numCols and numColGroups
|
||||
numCols = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
numColGroups = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
numCols = bb.getInt();
|
||||
numColGroups = bb.getInt();
|
||||
|
||||
// read in the row-number index
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndex = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
rowIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
len = bb.getInt();
|
||||
rowIndex = new short[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rowIndex[i] = bb.getShort();
|
||||
}
|
||||
|
||||
// load in the populated-cells bitmap: index first, then bitmap list
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexFlagsIndex = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
rowIndexFlagsIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
len = bb.getInt();
|
||||
rowIndexFlagsIndex = new short[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rowIndexFlagsIndex[i] = bb.getShort();
|
||||
}
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexFlags = new int[l];
|
||||
for (int i = 0; i < l; i++, offset+=4) {
|
||||
rowIndexFlags[i] = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
len = bb.getInt();
|
||||
rowIndexFlags = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rowIndexFlags[i] = bb.getInt();
|
||||
}
|
||||
|
||||
// load in the row-shift index
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexShifts = new byte[l];
|
||||
for (int i = 0; i < l; i++, offset++) {
|
||||
rowIndexShifts[i] = buf[offset];
|
||||
}
|
||||
len = bb.getInt();
|
||||
rowIndexShifts = new byte[len];
|
||||
bb.get(rowIndexShifts);
|
||||
|
||||
// load in the actual state table
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
table = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
table[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
len = bb.getInt();
|
||||
table = new short[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
table[i] = bb.getShort();
|
||||
}
|
||||
|
||||
// finally, prepare the column map for supplementary characters
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
int[] temp3 = new int[l];
|
||||
for (int i = 0; i < l; i++, offset+=4) {
|
||||
temp3[i] = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
len = bb.getInt();
|
||||
int[] temp3 = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
temp3[i] = bb.getInt();
|
||||
}
|
||||
assert bb.position() == bb.limit();
|
||||
|
||||
supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,10 +38,8 @@
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
package sun.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Module;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -72,7 +70,7 @@ import java.util.Stack;
|
||||
* slow) BuildDictionaryFile utility for creating dictionary files, but aren't
|
||||
* currently making it public. Contact us for help.
|
||||
*/
|
||||
class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
|
||||
public class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
|
||||
|
||||
/**
|
||||
* a list of known words that is used to divide up contiguous ranges of letters,
|
||||
@ -109,18 +107,22 @@ class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
|
||||
|
||||
/**
|
||||
* Constructs a DictionaryBasedBreakIterator.
|
||||
* @param module The module where the dictionary file resides
|
||||
* @param dictionaryFilename The filename of the dictionary file to use
|
||||
*
|
||||
* @param ruleFile the name of the rule data file
|
||||
* @param ruleData the rule data loaded from the rule data file
|
||||
* @param dictionaryFile the name of the dictionary file
|
||||
* @param dictionartData the dictionary data loaded from the dictionary file
|
||||
* @throws MissingResourceException if rule data or dictionary initialization failed
|
||||
*/
|
||||
DictionaryBasedBreakIterator(Module module, String dataFile, String dictionaryFile)
|
||||
throws IOException {
|
||||
super(module, dataFile);
|
||||
public DictionaryBasedBreakIterator(String ruleFile, byte[] ruleData,
|
||||
String dictionaryFile, byte[] dictionaryData) {
|
||||
super(ruleFile, ruleData);
|
||||
byte[] tmp = super.getAdditionalData();
|
||||
if (tmp != null) {
|
||||
prepareCategoryFlags(tmp);
|
||||
super.setAdditionalData(null);
|
||||
}
|
||||
dictionary = new BreakDictionary(module, dictionaryFile);
|
||||
dictionary = new BreakDictionary(dictionaryFile, dictionaryData);
|
||||
}
|
||||
|
||||
private void prepareCategoryFlags(byte[] data) {
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,15 +38,10 @@
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
package sun.text;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
@ -218,7 +213,7 @@ import sun.text.SupplementaryCharacterData;
|
||||
*
|
||||
* @author Richard Gillam
|
||||
*/
|
||||
class RuleBasedBreakIterator extends BreakIterator {
|
||||
public class RuleBasedBreakIterator extends BreakIterator {
|
||||
|
||||
/**
|
||||
* A token used as a character-category value to identify ignore characters
|
||||
@ -249,11 +244,6 @@ class RuleBasedBreakIterator extends BreakIterator {
|
||||
*/
|
||||
static final byte supportedVersion = 1;
|
||||
|
||||
/**
|
||||
* Header size in byte count
|
||||
*/
|
||||
private static final int HEADER_LENGTH = 36;
|
||||
|
||||
/**
|
||||
* An array length of indices for BMP characters
|
||||
*/
|
||||
@ -315,16 +305,26 @@ class RuleBasedBreakIterator extends BreakIterator {
|
||||
//=======================================================================
|
||||
|
||||
/**
|
||||
* Constructs a RuleBasedBreakIterator according to the module and the datafile
|
||||
* provided.
|
||||
* Constructs a RuleBasedBreakIterator using the given rule data.
|
||||
*
|
||||
* @throws MissingResourceException if the rule data is invalid or corrupted
|
||||
*/
|
||||
RuleBasedBreakIterator(Module module, String datafile)
|
||||
throws IOException, MissingResourceException {
|
||||
readTables(module, datafile);
|
||||
public RuleBasedBreakIterator(String ruleFile, byte[] ruleData) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(ruleData);
|
||||
try {
|
||||
validateRuleData(ruleFile, bb);
|
||||
setupTables(ruleFile, bb);
|
||||
} catch (BufferUnderflowException bue) {
|
||||
MissingResourceException e;
|
||||
e = new MissingResourceException("Corrupted rule data file", ruleFile, "");
|
||||
e.initCause(bue);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read datafile. The datafile's format is as follows:
|
||||
* Initializes the fields with the given rule data.
|
||||
* The data format is as follows:
|
||||
* <pre>
|
||||
* BreakIteratorData {
|
||||
* u1 magic[7];
|
||||
@ -370,133 +370,101 @@ class RuleBasedBreakIterator extends BreakIterator {
|
||||
* u1 additionalData[additionalDataLength];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @throws BufferUnderflowException if the end-of-data is reached before
|
||||
* setting up all the tables
|
||||
*/
|
||||
protected final void readTables(Module module, String datafile)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
byte[] buffer = readFile(module, datafile);
|
||||
|
||||
private void setupTables(String ruleFile, ByteBuffer bb) {
|
||||
/* Read header_info. */
|
||||
int stateTableLength = getInt(buffer, 0);
|
||||
int backwardsStateTableLength = getInt(buffer, 4);
|
||||
int endStatesLength = getInt(buffer, 8);
|
||||
int lookaheadStatesLength = getInt(buffer, 12);
|
||||
int BMPdataLength = getInt(buffer, 16);
|
||||
int nonBMPdataLength = getInt(buffer, 20);
|
||||
int additionalDataLength = getInt(buffer, 24);
|
||||
checksum = getLong(buffer, 28);
|
||||
int stateTableLength = bb.getInt();
|
||||
int backwardsStateTableLength = bb.getInt();
|
||||
int endStatesLength = bb.getInt();
|
||||
int lookaheadStatesLength = bb.getInt();
|
||||
int BMPdataLength = bb.getInt();
|
||||
int nonBMPdataLength = bb.getInt();
|
||||
int additionalDataLength = bb.getInt();
|
||||
checksum = bb.getLong();
|
||||
|
||||
/* Read stateTable[numCategories * numRows] */
|
||||
stateTable = new short[stateTableLength];
|
||||
int offset = HEADER_LENGTH;
|
||||
for (int i = 0; i < stateTableLength; i++, offset+=2) {
|
||||
stateTable[i] = getShort(buffer, offset);
|
||||
for (int i = 0; i < stateTableLength; i++) {
|
||||
stateTable[i] = bb.getShort();
|
||||
}
|
||||
|
||||
/* Read backwardsStateTable[numCategories * numRows] */
|
||||
backwardsStateTable = new short[backwardsStateTableLength];
|
||||
for (int i = 0; i < backwardsStateTableLength; i++, offset+=2) {
|
||||
backwardsStateTable[i] = getShort(buffer, offset);
|
||||
for (int i = 0; i < backwardsStateTableLength; i++) {
|
||||
backwardsStateTable[i] = bb.getShort();
|
||||
}
|
||||
|
||||
/* Read endStates[numRows] */
|
||||
endStates = new boolean[endStatesLength];
|
||||
for (int i = 0; i < endStatesLength; i++, offset++) {
|
||||
endStates[i] = buffer[offset] == 1;
|
||||
for (int i = 0; i < endStatesLength; i++) {
|
||||
endStates[i] = bb.get() == 1;
|
||||
}
|
||||
|
||||
/* Read lookaheadStates[numRows] */
|
||||
lookaheadStates = new boolean[lookaheadStatesLength];
|
||||
for (int i = 0; i < lookaheadStatesLength; i++, offset++) {
|
||||
lookaheadStates[i] = buffer[offset] == 1;
|
||||
for (int i = 0; i < lookaheadStatesLength; i++) {
|
||||
lookaheadStates[i] = bb.get() == 1;
|
||||
}
|
||||
|
||||
/* Read a category table and indices for BMP characters. */
|
||||
short[] temp1 = new short[BMP_INDICES_LENGTH]; // BMPindices
|
||||
for (int i = 0; i < BMP_INDICES_LENGTH; i++, offset+=2) {
|
||||
temp1[i] = getShort(buffer, offset);
|
||||
for (int i = 0; i < BMP_INDICES_LENGTH; i++) {
|
||||
temp1[i] = bb.getShort();
|
||||
}
|
||||
byte[] temp2 = new byte[BMPdataLength]; // BMPdata
|
||||
System.arraycopy(buffer, offset, temp2, 0, BMPdataLength);
|
||||
offset += BMPdataLength;
|
||||
bb.get(temp2);
|
||||
charCategoryTable = new CompactByteArray(temp1, temp2);
|
||||
|
||||
/* Read a category table for non-BMP characters. */
|
||||
int[] temp3 = new int[nonBMPdataLength];
|
||||
for (int i = 0; i < nonBMPdataLength; i++, offset+=4) {
|
||||
temp3[i] = getInt(buffer, offset);
|
||||
for (int i = 0; i < nonBMPdataLength; i++) {
|
||||
temp3[i] = bb.getInt();
|
||||
}
|
||||
supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
|
||||
|
||||
/* Read additional data */
|
||||
if (additionalDataLength > 0) {
|
||||
additionalData = new byte[additionalDataLength];
|
||||
System.arraycopy(buffer, offset, additionalData, 0, additionalDataLength);
|
||||
bb.get(additionalData);
|
||||
}
|
||||
assert bb.position() == bb.limit();
|
||||
|
||||
/* Set numCategories */
|
||||
numCategories = stateTable.length / endStates.length;
|
||||
}
|
||||
|
||||
protected byte[] readFile(final Module module, final String datafile)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
BufferedInputStream is;
|
||||
try {
|
||||
PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
|
||||
String pathName = "jdk.localedata".equals(module.getName()) ?
|
||||
"sun/text/resources/ext/" :
|
||||
"sun/text/resources/";
|
||||
InputStream in = module.getResourceAsStream(pathName + datafile);
|
||||
if (in == null) {
|
||||
// Try to load the file with "java.base" module instance. Assumption
|
||||
// here is that the fall back data files to be read should reside in
|
||||
// java.base.
|
||||
in = RuleBasedBreakIterator.class.getModule().getResourceAsStream("sun/text/resources/" + datafile);
|
||||
}
|
||||
|
||||
return new BufferedInputStream(in);
|
||||
};
|
||||
is = AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
|
||||
/* First, read magic, version, and header_info. */
|
||||
int len = LABEL_LENGTH + 5;
|
||||
byte[] buf = new byte[len];
|
||||
if (is.read(buf) != len) {
|
||||
throw new MissingResourceException("Wrong header length",
|
||||
datafile, "");
|
||||
}
|
||||
|
||||
/* Validate the magic number. */
|
||||
for (int i = 0; i < LABEL_LENGTH; i++, offset++) {
|
||||
if (buf[offset] != LABEL[offset]) {
|
||||
/**
|
||||
* Validates the magic number, version, and the length of the given data.
|
||||
*
|
||||
* @throws BufferUnderflowException if the end-of-data is reached while
|
||||
* validating data
|
||||
* @throws MissingResourceException if valification failed
|
||||
*/
|
||||
void validateRuleData(String ruleFile, ByteBuffer bb) {
|
||||
/* Verify the magic number. */
|
||||
for (int i = 0; i < LABEL_LENGTH; i++) {
|
||||
if (bb.get() != LABEL[i]) {
|
||||
throw new MissingResourceException("Wrong magic number",
|
||||
datafile, "");
|
||||
ruleFile, "");
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate the version number. */
|
||||
if (buf[offset] != supportedVersion) {
|
||||
throw new MissingResourceException("Unsupported version(" + buf[offset] + ")",
|
||||
datafile, "");
|
||||
/* Verify the version number. */
|
||||
byte version = bb.get();
|
||||
if (version != supportedVersion) {
|
||||
throw new MissingResourceException("Unsupported version(" + version + ")",
|
||||
ruleFile, "");
|
||||
}
|
||||
|
||||
/* Read data: totalDataSize + 8(for checksum) */
|
||||
len = getInt(buf, ++offset);
|
||||
buf = new byte[len];
|
||||
if (is.read(buf) != len) {
|
||||
// Check the length of the rest of data
|
||||
int len = bb.getInt();
|
||||
if (bb.position() + len != bb.limit()) {
|
||||
throw new MissingResourceException("Wrong data length",
|
||||
datafile, "");
|
||||
ruleFile, "");
|
||||
}
|
||||
|
||||
is.close();
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
byte[] getAdditionalData() {
|
||||
@ -1061,28 +1029,6 @@ class RuleBasedBreakIterator extends BreakIterator {
|
||||
return backwardsStateTable[state * numCategories + category];
|
||||
}
|
||||
|
||||
static long getLong(byte[] buf, int offset) {
|
||||
long num = buf[offset]&0xFF;
|
||||
for (int i = 1; i < 8; i++) {
|
||||
num = num<<8 | (buf[offset+i]&0xFF);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static int getInt(byte[] buf, int offset) {
|
||||
int num = buf[offset]&0xFF;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
num = num<<8 | (buf[offset+i]&0xFF);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static short getShort(byte[] buf, int offset) {
|
||||
short num = (short)(buf[offset]&0xFF);
|
||||
num = (short)(num<<8 | (buf[offset+1]&0xFF));
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* This class exists to work around a bug in incorrect implementations
|
||||
* of CharacterIterator, which incorrectly handle setIndex(endIndex).
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.text.resources;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.resources.BreakIteratorResourceBundle;
|
||||
|
||||
public class BreakIteratorResources extends BreakIteratorResourceBundle {
|
||||
@Override
|
||||
protected ResourceBundle getBreakIteratorInfo() {
|
||||
return new BreakIteratorInfo();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,6 +32,8 @@ import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import sun.text.DictionaryBasedBreakIterator;
|
||||
import sun.text.RuleBasedBreakIterator;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.BreakIteratorProvider
|
||||
@ -154,28 +156,30 @@ public class BreakIteratorProviderImpl extends BreakIteratorProvider
|
||||
|
||||
private BreakIterator getBreakInstance(Locale locale,
|
||||
int type,
|
||||
String dataName,
|
||||
String ruleName,
|
||||
String dictionaryName) {
|
||||
Objects.requireNonNull(locale);
|
||||
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
|
||||
String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
|
||||
String dataFile = (String) lr.getBreakIteratorInfo(dataName);
|
||||
String ruleFile = (String) lr.getBreakIteratorInfo(ruleName);
|
||||
byte[] ruleData = lr.getBreakIteratorResources(ruleName);
|
||||
|
||||
try {
|
||||
switch (classNames[type]) {
|
||||
case "RuleBasedBreakIterator":
|
||||
return new RuleBasedBreakIterator(
|
||||
lr.getBreakIteratorDataModule(), dataFile);
|
||||
return new RuleBasedBreakIterator(ruleFile, ruleData);
|
||||
|
||||
case "DictionaryBasedBreakIterator":
|
||||
String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
|
||||
return new DictionaryBasedBreakIterator(
|
||||
lr.getBreakIteratorDataModule(), dataFile, dictionaryFile);
|
||||
byte[] dictionaryData = lr.getBreakIteratorResources(dictionaryName);
|
||||
return new DictionaryBasedBreakIterator(ruleFile, ruleData,
|
||||
dictionaryFile, dictionaryData);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid break iterator class \"" +
|
||||
classNames[type] + "\"");
|
||||
}
|
||||
} catch (IOException | MissingResourceException | IllegalArgumentException e) {
|
||||
} catch (MissingResourceException | IllegalArgumentException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -42,7 +42,6 @@ package sun.util.locale.provider;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.Module;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -118,8 +117,9 @@ public class LocaleResources {
|
||||
return biInfo;
|
||||
}
|
||||
|
||||
Module getBreakIteratorDataModule() {
|
||||
return localeData.getBreakIteratorInfo(locale).getClass().getModule();
|
||||
@SuppressWarnings("unchecked")
|
||||
byte[] getBreakIteratorResources(String key) {
|
||||
return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
|
||||
}
|
||||
|
||||
int getCalendarData(String key) {
|
||||
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* BreakIteratorResourceBundle is an abstract class for loading BreakIterator
|
||||
* data (rules or dictionary) from each module. An implementation class must
|
||||
* implement getBreakIteratorInfo() that returns an instance of the
|
||||
* corresponding BreakIteratorInfo (basename). The data name is taken from the
|
||||
* BreakIteratorInfo instance.
|
||||
*
|
||||
* <p>For example, if the given key is "WordDictionary" and Locale is "th", the
|
||||
* data name is taken from a BreakIteratorInfo_th and the key's value is
|
||||
* "thai_dict". Its data thai_dict is loaded from the Module of the
|
||||
* implementation class of this class.
|
||||
*/
|
||||
|
||||
public abstract class BreakIteratorResourceBundle extends ResourceBundle {
|
||||
// If any keys that are not for data names are added to BreakIteratorInfo*,
|
||||
// those keys must be added to NON_DATA_KEYS.
|
||||
private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
|
||||
|
||||
private volatile Set<String> keys;
|
||||
|
||||
/**
|
||||
* Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
|
||||
* The instance shouldn't have its parent.
|
||||
*/
|
||||
protected abstract ResourceBundle getBreakIteratorInfo();
|
||||
|
||||
@Override
|
||||
protected Object handleGetObject(String key) {
|
||||
if (NON_DATA_KEYS.contains(key)) {
|
||||
return null;
|
||||
}
|
||||
ResourceBundle info = getBreakIteratorInfo();
|
||||
if (!info.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
String path = getClass().getPackage().getName().replace('.', '/')
|
||||
+ '/' + info.getString(key);
|
||||
byte[] data;
|
||||
try (InputStream is = getResourceAsStream(path)) {
|
||||
data = is.readAllBytes();
|
||||
} catch (Exception e) {
|
||||
throw new InternalError("Can't load " + path, e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private InputStream getResourceAsStream(String path) throws Exception {
|
||||
PrivilegedExceptionAction<InputStream> pa;
|
||||
pa = () -> getClass().getModule().getResourceAsStream(path);
|
||||
InputStream is;
|
||||
try {
|
||||
is = AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getException();
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getKeys() {
|
||||
return Collections.enumeration(keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> handleKeySet() {
|
||||
if (keys == null) {
|
||||
ResourceBundle info = getBreakIteratorInfo();
|
||||
Set<String> k = info.keySet();
|
||||
k.removeAll(NON_DATA_KEYS);
|
||||
synchronized (this) {
|
||||
if (keys == null) {
|
||||
keys = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
}
|
@ -122,6 +122,14 @@ public class LocaleData {
|
||||
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorInfo", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a break iterator resources resource bundle, using
|
||||
* privileges to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getBreakIteratorResources(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorResources", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collation data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.text.resources.ext;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.resources.BreakIteratorResourceBundle;
|
||||
|
||||
public class BreakIteratorResources_th extends BreakIteratorResourceBundle {
|
||||
@Override
|
||||
protected ResourceBundle getBreakIteratorInfo() {
|
||||
return new BreakIteratorInfo_th();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -89,7 +89,7 @@ public class BreakIteratorProviderTest extends ProviderTest {
|
||||
String[] jresResult = new String[4];
|
||||
if (jreSupportsLocale) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
jresResult[i] = "sun.util.locale.provider."+classNames[i];
|
||||
jresResult[i] = "sun.text." + classNames[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,6 @@
|
||||
#
|
||||
#
|
||||
# @test
|
||||
# @bug 4052440 8062588
|
||||
# @bug 4052440 8062588 8165804
|
||||
# @summary BreakIteratorProvider tests
|
||||
# @run shell ExecTest.sh foo BreakIteratorProviderTest
|
||||
|
@ -40,7 +40,7 @@ import tests.Result;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8152143 8152704 8155649
|
||||
* @bug 8152143 8152704 8155649 8165804
|
||||
* @summary IncludeLocalesPlugin tests
|
||||
* @author Naoto Sato
|
||||
* @library ../../lib
|
||||
@ -236,6 +236,7 @@ public class IncludeLocalesPluginTest {
|
||||
"/jdk.localedata/sun/text/resources/ext/thai_dict",
|
||||
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
|
||||
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
|
||||
@ -261,6 +262,7 @@ public class IncludeLocalesPluginTest {
|
||||
"/jdk.localedata/sun/text/resources/ext/thai_dict",
|
||||
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
|
||||
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
|
||||
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class"),
|
||||
List.of(
|
||||
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
|
||||
|
Loading…
x
Reference in New Issue
Block a user