Merge
This commit is contained in:
commit
cd7e00cd53
@ -37,7 +37,7 @@ PRODUCT = sun
|
|||||||
# This re-directs all the class files to a separate location
|
# This re-directs all the class files to a separate location
|
||||||
CLASSDESTDIR = $(TEMPDIR)/classes
|
CLASSDESTDIR = $(TEMPDIR)/classes
|
||||||
|
|
||||||
OTHER_JAVACFLAGS += -Xlint:serial -Werror
|
OTHER_JAVACFLAGS += -Xlint:serial,-deprecation -Werror
|
||||||
include $(BUILDDIR)/common/Defs.gmk
|
include $(BUILDDIR)/common/Defs.gmk
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -418,6 +418,8 @@ public final class ProcessBuilder
|
|||||||
* Implements a <a href="#redirect-output">null input stream</a>.
|
* Implements a <a href="#redirect-output">null input stream</a>.
|
||||||
*/
|
*/
|
||||||
static class NullInputStream extends InputStream {
|
static class NullInputStream extends InputStream {
|
||||||
|
static final NullInputStream INSTANCE = new NullInputStream();
|
||||||
|
private NullInputStream() {}
|
||||||
public int read() { return -1; }
|
public int read() { return -1; }
|
||||||
public int available() { return 0; }
|
public int available() { return 0; }
|
||||||
}
|
}
|
||||||
@ -426,6 +428,8 @@ public final class ProcessBuilder
|
|||||||
* Implements a <a href="#redirect-input">null output stream</a>.
|
* Implements a <a href="#redirect-input">null output stream</a>.
|
||||||
*/
|
*/
|
||||||
static class NullOutputStream extends OutputStream {
|
static class NullOutputStream extends OutputStream {
|
||||||
|
static final NullOutputStream INSTANCE = new NullOutputStream();
|
||||||
|
private NullOutputStream() {}
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
throw new IOException("Stream closed");
|
throw new IOException("Stream closed");
|
||||||
}
|
}
|
||||||
|
@ -124,15 +124,15 @@ public abstract class ByteToCharISO2022 extends ByteToCharConverter
|
|||||||
switch(shiftFlag) {
|
switch(shiftFlag) {
|
||||||
case SOFlag:
|
case SOFlag:
|
||||||
tmpIndex = curSODes;
|
tmpIndex = curSODes;
|
||||||
tmpConverter = (ByteToCharConverter [])SOConverter;
|
tmpConverter = SOConverter;
|
||||||
break;
|
break;
|
||||||
case SS2Flag:
|
case SS2Flag:
|
||||||
tmpIndex = curSS2Des;
|
tmpIndex = curSS2Des;
|
||||||
tmpConverter = (ByteToCharConverter [])SS2Converter;
|
tmpConverter = SS2Converter;
|
||||||
break;
|
break;
|
||||||
case SS3Flag:
|
case SS3Flag:
|
||||||
tmpIndex = curSS3Des;
|
tmpIndex = curSS3Des;
|
||||||
tmpConverter = (ByteToCharConverter [])SS3Converter;
|
tmpConverter = SS3Converter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public class ByteToCharISO2022JP extends ByteToCharJIS0208 {
|
|||||||
} else {
|
} else {
|
||||||
savedSize = 2;
|
savedSize = 2;
|
||||||
savedBytes[0] = (byte)byte1;
|
savedBytes[0] = (byte)byte1;
|
||||||
savedBytes[1] = (byte)input[readOff + inputSize];
|
savedBytes[1] = input[readOff + inputSize];
|
||||||
inputSize++;
|
inputSize++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -34,14 +34,12 @@ public class ByteToCharJISAutoDetect extends ByteToCharConverter {
|
|||||||
private final static int SJIS1B_MASK = 0x04;
|
private final static int SJIS1B_MASK = 0x04;
|
||||||
private final static int EUCJP_KANA1_MASK = 0x08;
|
private final static int EUCJP_KANA1_MASK = 0x08;
|
||||||
private final static int EUCJP_KANA2_MASK = 0x10;
|
private final static int EUCJP_KANA2_MASK = 0x10;
|
||||||
private static byte[] maskTable1;
|
private final static byte[] maskTable1 = JISAutoDetect.getByteMask1();
|
||||||
private static byte[] maskTable2;
|
private final static byte[] maskTable2 = JISAutoDetect.getByteMask2();
|
||||||
|
|
||||||
private final static int SS2 = 0x8e;
|
private final static int SS2 = 0x8e;
|
||||||
private final static int SS3 = 0x8f;
|
private final static int SS3 = 0x8f;
|
||||||
|
|
||||||
private final static JISAutoDetect nioCoder = new JISAutoDetect();
|
|
||||||
|
|
||||||
// SJISName is set to either "SJIS" or "MS932"
|
// SJISName is set to either "SJIS" or "MS932"
|
||||||
private String SJISName;
|
private String SJISName;
|
||||||
private String EUCJPName;
|
private String EUCJPName;
|
||||||
@ -57,8 +55,6 @@ public class ByteToCharJISAutoDetect extends ByteToCharConverter {
|
|||||||
defaultConv = new ByteToCharISO8859_1();
|
defaultConv = new ByteToCharISO8859_1();
|
||||||
defaultConv.subChars = subChars;
|
defaultConv.subChars = subChars;
|
||||||
defaultConv.subMode = subMode;
|
defaultConv.subMode = subMode;
|
||||||
maskTable1 = nioCoder.getByteMask1();
|
|
||||||
maskTable2 = nioCoder.getByteMask2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int flush(char [] output, int outStart, int outEnd)
|
public int flush(char [] output, int outStart, int outEnd)
|
||||||
@ -133,7 +129,7 @@ public class ByteToCharJISAutoDetect extends ByteToCharConverter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((mask == SJIS2B_MASK) || (mask == SJIS1B_MASK)
|
if ((mask == SJIS2B_MASK) || (mask == SJIS1B_MASK)
|
||||||
|| (nioCoder.canBeSJIS1B(firstmask) && secondmask == 0)) {
|
|| (JISAutoDetect.canBeSJIS1B(firstmask) && secondmask == 0)) {
|
||||||
convName = SJISName;
|
convName = SJISName;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -145,15 +141,15 @@ public class ByteToCharJISAutoDetect extends ByteToCharConverter {
|
|||||||
// character boundary. If we tried both
|
// character boundary. If we tried both
|
||||||
// possibilities here, it might be able to be
|
// possibilities here, it might be able to be
|
||||||
// determined correctly.
|
// determined correctly.
|
||||||
if ((byte1 == SS3) && nioCoder.canBeEUCJP(secondmask)) {
|
if ((byte1 == SS3) && JISAutoDetect.canBeEUCJP(secondmask)) {
|
||||||
if (cnt+1 < inEnd) {
|
if (cnt+1 < inEnd) {
|
||||||
int nextbyte = input[cnt+1] & 0xff;
|
int nextbyte = input[cnt+1] & 0xff;
|
||||||
if (! nioCoder.canBeEUCJP(maskTable2[nextbyte]))
|
if (! JISAutoDetect.canBeEUCJP(maskTable2[nextbyte]))
|
||||||
convName = SJISName;
|
convName = SJISName;
|
||||||
} else
|
} else
|
||||||
convName = SJISName;
|
convName = SJISName;
|
||||||
}
|
}
|
||||||
if (nioCoder.canBeEUCKana(firstmask, secondmask))
|
if (JISAutoDetect.canBeEUCKana(firstmask, secondmask))
|
||||||
euckana++;
|
euckana++;
|
||||||
} else {
|
} else {
|
||||||
if ((firstmask & SJIS1B_MASK) != 0) {
|
if ((firstmask & SJIS1B_MASK) != 0) {
|
||||||
|
@ -66,7 +66,7 @@ public class CharToBytePCK extends CharToByteSJIS {
|
|||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '\u2015':
|
case '\u2015':
|
||||||
return (int)0x815C;
|
return 0x815C;
|
||||||
case '\u2014':
|
case '\u2014':
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
@ -103,7 +103,7 @@ public class DoubleByte {
|
|||||||
public final static char[] B2C_UNMAPPABLE;
|
public final static char[] B2C_UNMAPPABLE;
|
||||||
static {
|
static {
|
||||||
B2C_UNMAPPABLE = new char[0x100];
|
B2C_UNMAPPABLE = new char[0x100];
|
||||||
Arrays.fill(B2C_UNMAPPABLE, (char)UNMAPPABLE_DECODING);
|
Arrays.fill(B2C_UNMAPPABLE, UNMAPPABLE_DECODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Decoder extends CharsetDecoder
|
public static class Decoder extends CharsetDecoder
|
||||||
@ -374,7 +374,7 @@ public class DoubleByte {
|
|||||||
static final char[] b2cSB;
|
static final char[] b2cSB;
|
||||||
static {
|
static {
|
||||||
b2cSB = new char[0x100];
|
b2cSB = new char[0x100];
|
||||||
Arrays.fill(b2cSB, (char)UNMAPPABLE_DECODING);
|
Arrays.fill(b2cSB, UNMAPPABLE_DECODING);
|
||||||
}
|
}
|
||||||
Decoder_EBCDIC_DBCSONLY(Charset cs, char[][] b2c, int b2Min, int b2Max) {
|
Decoder_EBCDIC_DBCSONLY(Charset cs, char[][] b2c, int b2Min, int b2Max) {
|
||||||
super(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
|
super(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
|
||||||
|
@ -79,8 +79,10 @@ public class EUC_JP
|
|||||||
JIS_X_0201.Decoder decoderJ0201;
|
JIS_X_0201.Decoder decoderJ0201;
|
||||||
JIS_X_0212_Decoder decoderJ0212;
|
JIS_X_0212_Decoder decoderJ0212;
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Decoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Decoder.getIndex2();
|
||||||
|
|
||||||
protected Decoder(Charset cs) {
|
protected Decoder(Charset cs) {
|
||||||
super(cs);
|
super(cs);
|
||||||
@ -88,8 +90,6 @@ public class EUC_JP
|
|||||||
decoderJ0212 = new JIS_X_0212_Decoder(cs);
|
decoderJ0212 = new JIS_X_0212_Decoder(cs);
|
||||||
start = 0xa1;
|
start = 0xa1;
|
||||||
end = 0xfe;
|
end = 0xfe;
|
||||||
j0208Index1 = super.getIndex1();
|
|
||||||
j0208Index2 = super.getIndex2();
|
|
||||||
}
|
}
|
||||||
protected char decode0212(int byte1, int byte2) {
|
protected char decode0212(int byte1, int byte2) {
|
||||||
return decoderJ0212.decodeDouble(byte1, byte2);
|
return decoderJ0212.decodeDouble(byte1, byte2);
|
||||||
@ -238,8 +238,10 @@ public class EUC_JP
|
|||||||
JIS_X_0201.Encoder encoderJ0201;
|
JIS_X_0201.Encoder encoderJ0201;
|
||||||
JIS_X_0212_Encoder encoderJ0212;
|
JIS_X_0212_Encoder encoderJ0212;
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Encoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Encoder.getIndex2();
|
||||||
|
|
||||||
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
||||||
|
|
||||||
@ -247,8 +249,6 @@ public class EUC_JP
|
|||||||
super(cs, 3.0f, 3.0f);
|
super(cs, 3.0f, 3.0f);
|
||||||
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
||||||
encoderJ0212 = new JIS_X_0212_Encoder(cs);
|
encoderJ0212 = new JIS_X_0212_Encoder(cs);
|
||||||
j0208Index1 = super.getIndex1();
|
|
||||||
j0208Index2 = super.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canEncode(char c) {
|
public boolean canEncode(char c) {
|
||||||
|
@ -65,20 +65,18 @@ public class EUC_JP_LINUX
|
|||||||
|
|
||||||
private static class Decoder extends CharsetDecoder {
|
private static class Decoder extends CharsetDecoder {
|
||||||
JIS_X_0201.Decoder decoderJ0201;
|
JIS_X_0201.Decoder decoderJ0201;
|
||||||
JIS_X_0208_Decoder decodeMappingJ0208;
|
|
||||||
protected final char REPLACE_CHAR='\uFFFD';
|
protected final char REPLACE_CHAR='\uFFFD';
|
||||||
|
|
||||||
short[] jis0208Index1;
|
private static final int start = 0xa1;
|
||||||
String[] jis0208Index2;
|
private static final int end = 0xfe;
|
||||||
|
private static final short[] jis0208Index1 =
|
||||||
|
JIS_X_0208_Decoder.getIndex1();
|
||||||
|
private static final String[] jis0208Index2 =
|
||||||
|
JIS_X_0208_Decoder.getIndex2();
|
||||||
|
|
||||||
private Decoder(Charset cs) {
|
private Decoder(Charset cs) {
|
||||||
super(cs, 1.0f, 1.0f);
|
super(cs, 1.0f, 1.0f);
|
||||||
decoderJ0201 = new JIS_X_0201.Decoder(cs);
|
decoderJ0201 = new JIS_X_0201.Decoder(cs);
|
||||||
decodeMappingJ0208 = new JIS_X_0208_Decoder(cs);
|
|
||||||
decodeMappingJ0208.start = 0xa1;
|
|
||||||
decodeMappingJ0208.end = 0xfe;
|
|
||||||
jis0208Index1 = decodeMappingJ0208.getIndex1();
|
|
||||||
jis0208Index2 = decodeMappingJ0208.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected char convSingleByte(int b) {
|
protected char convSingleByte(int b) {
|
||||||
@ -93,11 +91,11 @@ public class EUC_JP_LINUX
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (((byte1 < 0) || (byte1 > jis0208Index1.length))
|
if (((byte1 < 0) || (byte1 > jis0208Index1.length))
|
||||||
|| ((byte2 < decodeMappingJ0208.start) || (byte2 > decodeMappingJ0208.end)))
|
|| ((byte2 < start) || (byte2 > end)))
|
||||||
return REPLACE_CHAR;
|
return REPLACE_CHAR;
|
||||||
|
|
||||||
int n = (jis0208Index1[byte1 - 0x80] & 0xf) * (decodeMappingJ0208.end - decodeMappingJ0208.start + 1)
|
int n = (jis0208Index1[byte1 - 0x80] & 0xf) * (end - start + 1)
|
||||||
+ (byte2 - decodeMappingJ0208.start);
|
+ (byte2 - start);
|
||||||
return jis0208Index2[jis0208Index1[byte1 - 0x80] >> 4].charAt(n);
|
return jis0208Index2[jis0208Index1[byte1 - 0x80] >> 4].charAt(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,18 +211,16 @@ public class EUC_JP_LINUX
|
|||||||
private static class Encoder extends CharsetEncoder {
|
private static class Encoder extends CharsetEncoder {
|
||||||
|
|
||||||
JIS_X_0201.Encoder encoderJ0201;
|
JIS_X_0201.Encoder encoderJ0201;
|
||||||
JIS_X_0208_Encoder encoderJ0208;
|
|
||||||
|
|
||||||
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
||||||
short[] jis0208Index1;
|
private static final short[] jis0208Index1 =
|
||||||
String[] jis0208Index2;
|
JIS_X_0208_Encoder.getIndex1();
|
||||||
|
private static final String[] jis0208Index2 =
|
||||||
|
JIS_X_0208_Encoder.getIndex2();
|
||||||
|
|
||||||
private Encoder(Charset cs) {
|
private Encoder(Charset cs) {
|
||||||
super(cs, 2.0f, 2.0f);
|
super(cs, 2.0f, 2.0f);
|
||||||
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
||||||
encoderJ0208 = new JIS_X_0208_Encoder(cs);
|
|
||||||
jis0208Index1 = encoderJ0208.getIndex1();
|
|
||||||
jis0208Index2 = encoderJ0208.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canEncode(char c) {
|
public boolean canEncode(char c) {
|
||||||
|
@ -75,8 +75,12 @@ public class EUC_JP_Open
|
|||||||
JIS_X_0212_Solaris_Decoder decodeMappingJ0212;
|
JIS_X_0212_Solaris_Decoder decodeMappingJ0212;
|
||||||
JIS_X_0208_Solaris_Decoder decodeMappingJ0208;
|
JIS_X_0208_Solaris_Decoder decodeMappingJ0208;
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Solaris_Decoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Solaris_Decoder.getIndex2();
|
||||||
|
private static final int start = 0xa1;
|
||||||
|
private static final int end = 0xfe;
|
||||||
|
|
||||||
protected final char REPLACE_CHAR='\uFFFD';
|
protected final char REPLACE_CHAR='\uFFFD';
|
||||||
|
|
||||||
@ -84,11 +88,6 @@ public class EUC_JP_Open
|
|||||||
super(cs);
|
super(cs);
|
||||||
decoderJ0201 = new JIS_X_0201.Decoder(cs);
|
decoderJ0201 = new JIS_X_0201.Decoder(cs);
|
||||||
decodeMappingJ0212 = new JIS_X_0212_Solaris_Decoder(cs);
|
decodeMappingJ0212 = new JIS_X_0212_Solaris_Decoder(cs);
|
||||||
decodeMappingJ0208 = new JIS_X_0208_Solaris_Decoder(cs);
|
|
||||||
decodeMappingJ0208.start = 0xa1;
|
|
||||||
decodeMappingJ0208.end = 0xfe;
|
|
||||||
j0208Index1 = decodeMappingJ0208.getIndex1();
|
|
||||||
j0208Index2 = decodeMappingJ0208.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -103,9 +102,9 @@ public class EUC_JP_Open
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (((byte1 < 0)
|
if (((byte1 < 0)
|
||||||
|| (byte1 > decodeMappingJ0208.getIndex1().length))
|
|| (byte1 > j0208Index1.length))
|
||||||
|| ((byte2 < decodeMappingJ0208.start)
|
|| ((byte2 < start)
|
||||||
|| (byte2 > decodeMappingJ0208.end)))
|
|| (byte2 > end)))
|
||||||
return REPLACE_CHAR;
|
return REPLACE_CHAR;
|
||||||
|
|
||||||
char result = super.decodeDouble(byte1, byte2);
|
char result = super.decodeDouble(byte1, byte2);
|
||||||
@ -113,8 +112,8 @@ public class EUC_JP_Open
|
|||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
int n = (j0208Index1[byte1 - 0x80] & 0xf) *
|
int n = (j0208Index1[byte1 - 0x80] & 0xf) *
|
||||||
(decodeMappingJ0208.end - decodeMappingJ0208.start + 1)
|
(end - start + 1)
|
||||||
+ (byte2 - decodeMappingJ0208.start);
|
+ (byte2 - start);
|
||||||
return j0208Index2[j0208Index1[byte1 - 0x80] >> 4].charAt(n);
|
return j0208Index2[j0208Index1[byte1 - 0x80] >> 4].charAt(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,10 +124,11 @@ public class EUC_JP_Open
|
|||||||
|
|
||||||
JIS_X_0201.Encoder encoderJ0201;
|
JIS_X_0201.Encoder encoderJ0201;
|
||||||
JIS_X_0212_Solaris_Encoder encoderJ0212;
|
JIS_X_0212_Solaris_Encoder encoderJ0212;
|
||||||
JIS_X_0208_Solaris_Encoder encoderJ0208;
|
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Solaris_Encoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Solaris_Encoder.getIndex2();
|
||||||
|
|
||||||
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
private final Surrogate.Parser sgp = new Surrogate.Parser();
|
||||||
|
|
||||||
@ -136,9 +136,6 @@ public class EUC_JP_Open
|
|||||||
super(cs);
|
super(cs);
|
||||||
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
encoderJ0201 = new JIS_X_0201.Encoder(cs);
|
||||||
encoderJ0212 = new JIS_X_0212_Solaris_Encoder(cs);
|
encoderJ0212 = new JIS_X_0212_Solaris_Encoder(cs);
|
||||||
encoderJ0208 = new JIS_X_0208_Solaris_Encoder(cs);
|
|
||||||
j0208Index1 = encoderJ0208.getIndex1();
|
|
||||||
j0208Index2 = encoderJ0208.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int encodeSingle(char inputChar, byte[] outputByte) {
|
protected int encodeSingle(char inputChar, byte[] outputByte) {
|
||||||
|
@ -423,7 +423,7 @@ public class EUC_TW extends Charset implements HistoricallyNamedCharset
|
|||||||
if (dst.remaining() < outSize)
|
if (dst.remaining() < outSize)
|
||||||
return CoderResult.OVERFLOW;
|
return CoderResult.OVERFLOW;
|
||||||
for (int i = 0; i < outSize; i++)
|
for (int i = 0; i < outSize; i++)
|
||||||
dst.put((byte)bb[i]);
|
dst.put(bb[i]);
|
||||||
mark += inSize;
|
mark += inSize;
|
||||||
}
|
}
|
||||||
return CoderResult.UNDERFLOW;
|
return CoderResult.UNDERFLOW;
|
||||||
|
@ -12339,7 +12339,7 @@ public class GB18030
|
|||||||
int start = 0x40, end = 0xFE;
|
int start = 0x40, end = 0xFE;
|
||||||
if (((byte1 < 0) || (byte1 > index1.length))
|
if (((byte1 < 0) || (byte1 > index1.length))
|
||||||
|| ((byte2 < start) || (byte2 > end)))
|
|| ((byte2 < start) || (byte2 > end)))
|
||||||
return (char)'\uFFFD';
|
return '\uFFFD';
|
||||||
|
|
||||||
int n = (index1[byte1] & 0xf) * (end - start + 1) + (byte2 - start);
|
int n = (index1[byte1] & 0xf) * (end - start + 1) + (byte2 - start);
|
||||||
return index2[index1[byte1] >> 4].charAt(n);
|
return index2[index1[byte1] >> 4].charAt(n);
|
||||||
|
@ -43,7 +43,7 @@ public class HKSCS {
|
|||||||
|
|
||||||
private char[][] b2cBmp;
|
private char[][] b2cBmp;
|
||||||
private char[][] b2cSupp;
|
private char[][] b2cSupp;
|
||||||
private static DoubleByte.Decoder big5Dec;
|
private DoubleByte.Decoder big5Dec;
|
||||||
|
|
||||||
protected Decoder(Charset cs,
|
protected Decoder(Charset cs,
|
||||||
DoubleByte.Decoder big5Dec,
|
DoubleByte.Decoder big5Dec,
|
||||||
@ -355,7 +355,7 @@ public class HKSCS {
|
|||||||
c2b[hi] = new char[0x100];
|
c2b[hi] = new char[0x100];
|
||||||
Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
|
Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
|
||||||
}
|
}
|
||||||
c2b[hi][c & 0xff] = (char)bb;
|
c2b[hi][c & 0xff] = bb;
|
||||||
}
|
}
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
@ -104,15 +104,15 @@ abstract class ISO2022
|
|||||||
switch(shiftFlag) {
|
switch(shiftFlag) {
|
||||||
case SOFlag:
|
case SOFlag:
|
||||||
tmpIndex = curSODes;
|
tmpIndex = curSODes;
|
||||||
tmpDecoder = (CharsetDecoder [])SODecoder;
|
tmpDecoder = SODecoder;
|
||||||
break;
|
break;
|
||||||
case SS2Flag:
|
case SS2Flag:
|
||||||
tmpIndex = curSS2Des;
|
tmpIndex = curSS2Des;
|
||||||
tmpDecoder = (CharsetDecoder [])SS2Decoder;
|
tmpDecoder = SS2Decoder;
|
||||||
break;
|
break;
|
||||||
case SS3Flag:
|
case SS3Flag:
|
||||||
tmpIndex = curSS3Des;
|
tmpIndex = curSS3Des;
|
||||||
tmpDecoder = (CharsetDecoder [])SS3Decoder;
|
tmpDecoder = SS3Decoder;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +82,11 @@ public class JISAutoDetect
|
|||||||
* with the sun.io JISAutoDetect implementation
|
* with the sun.io JISAutoDetect implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public byte[] getByteMask1() {
|
public static byte[] getByteMask1() {
|
||||||
return Decoder.maskTable1;
|
return Decoder.maskTable1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getByteMask2() {
|
public static byte[] getByteMask2() {
|
||||||
return Decoder.maskTable2;
|
return Decoder.maskTable2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,17 +101,15 @@ public class PCK
|
|||||||
private static class Encoder extends SJIS.Encoder {
|
private static class Encoder extends SJIS.Encoder {
|
||||||
|
|
||||||
private JIS_X_0201.Encoder jis0201;
|
private JIS_X_0201.Encoder jis0201;
|
||||||
private JIS_X_0208_Solaris_Encoder jis0208;
|
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Solaris_Encoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Solaris_Encoder.getIndex2();
|
||||||
|
|
||||||
private Encoder(Charset cs) {
|
private Encoder(Charset cs) {
|
||||||
super(cs);
|
super(cs);
|
||||||
jis0201 = new JIS_X_0201.Encoder(cs);
|
jis0201 = new JIS_X_0201.Encoder(cs);
|
||||||
jis0208 = new JIS_X_0208_Solaris_Encoder(cs);
|
|
||||||
j0208Index1 = jis0208.getIndex1();
|
|
||||||
j0208Index2 = jis0208.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int encodeDouble(char ch) {
|
protected int encodeDouble(char ch) {
|
||||||
@ -121,7 +119,7 @@ public class PCK
|
|||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '\u2015':
|
case '\u2015':
|
||||||
return (int)0x815C;
|
return 0x815C;
|
||||||
case '\u2014':
|
case '\u2014':
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
@ -114,14 +114,14 @@ public class SJIS
|
|||||||
|
|
||||||
private JIS_X_0201.Encoder jis0201;
|
private JIS_X_0201.Encoder jis0201;
|
||||||
|
|
||||||
short[] j0208Index1;
|
private static final short[] j0208Index1 =
|
||||||
String[] j0208Index2;
|
JIS_X_0208_Encoder.getIndex1();
|
||||||
|
private static final String[] j0208Index2 =
|
||||||
|
JIS_X_0208_Encoder.getIndex2();
|
||||||
|
|
||||||
protected Encoder(Charset cs) {
|
protected Encoder(Charset cs) {
|
||||||
super(cs);
|
super(cs);
|
||||||
jis0201 = new JIS_X_0201.Encoder(cs);
|
jis0201 = new JIS_X_0201.Encoder(cs);
|
||||||
j0208Index1 = super.getIndex1();
|
|
||||||
j0208Index2 = super.getIndex2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int encodeSingle(char inputChar) {
|
protected int encodeSingle(char inputChar) {
|
||||||
|
@ -25,25 +25,42 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
/* java.lang.Process subclass in the UNIX environment.
|
/**
|
||||||
|
* java.lang.Process subclass in the UNIX environment.
|
||||||
*
|
*
|
||||||
* @author Mario Wolczko and Ross Knippel.
|
* @author Mario Wolczko and Ross Knippel.
|
||||||
* @author Konstantin Kladko (ported to Linux)
|
* @author Konstantin Kladko (ported to Linux)
|
||||||
|
* @author Martin Buchholz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class UNIXProcess extends Process {
|
final class UNIXProcess extends Process {
|
||||||
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
|
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
|
||||||
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
|
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||||
|
|
||||||
private int pid;
|
private final int pid;
|
||||||
private int exitcode;
|
private int exitcode;
|
||||||
private boolean hasExited;
|
private boolean hasExited;
|
||||||
|
|
||||||
private OutputStream stdin_stream;
|
private /* final */ OutputStream stdin;
|
||||||
private InputStream stdout_stream;
|
private /* final */ InputStream stdout;
|
||||||
private InputStream stderr_stream;
|
private /* final */ InputStream stderr;
|
||||||
|
|
||||||
/* this is for the reaping thread */
|
/* this is for the reaping thread */
|
||||||
private native int waitForProcessExit(int pid);
|
private native int waitForProcessExit(int pid);
|
||||||
@ -51,155 +68,136 @@ final class UNIXProcess extends Process {
|
|||||||
/**
|
/**
|
||||||
* Create a process using fork(2) and exec(2).
|
* Create a process using fork(2) and exec(2).
|
||||||
*
|
*
|
||||||
* @param std_fds array of file descriptors. Indexes 0, 1, and
|
* @param fds an array of three file descriptors.
|
||||||
* 2 correspond to standard input, standard output and
|
* Indexes 0, 1, and 2 correspond to standard input,
|
||||||
* standard error, respectively. On input, a value of -1
|
* standard output and standard error, respectively. On
|
||||||
* means to create a pipe to connect child and parent
|
* input, a value of -1 means to create a pipe to connect
|
||||||
* processes. On output, a value which is not -1 is the
|
* child and parent processes. On output, a value which
|
||||||
* parent pipe fd corresponding to the pipe which has
|
* is not -1 is the parent pipe fd corresponding to the
|
||||||
* been created. An element of this array is -1 on input
|
* pipe which has been created. An element of this array
|
||||||
* if and only if it is <em>not</em> -1 on output.
|
* is -1 on input if and only if it is <em>not</em> -1 on
|
||||||
|
* output.
|
||||||
* @return the pid of the subprocess
|
* @return the pid of the subprocess
|
||||||
*/
|
*/
|
||||||
private native int forkAndExec(byte[] prog,
|
private native int forkAndExec(byte[] prog,
|
||||||
byte[] argBlock, int argc,
|
byte[] argBlock, int argc,
|
||||||
byte[] envBlock, int envc,
|
byte[] envBlock, int envc,
|
||||||
byte[] dir,
|
byte[] dir,
|
||||||
int[] std_fds,
|
int[] fds,
|
||||||
boolean redirectErrorStream)
|
boolean redirectErrorStream)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/* In the process constructor we wait on this gate until the process */
|
/**
|
||||||
/* has been created. Then we return from the constructor. */
|
* The thread factory used to create "process reaper" daemon threads.
|
||||||
/* fork() is called by the same thread which later waits for the process */
|
*/
|
||||||
/* to terminate */
|
private static class ProcessReaperThreadFactory implements ThreadFactory {
|
||||||
|
private final static ThreadGroup group = getRootThreadGroup();
|
||||||
|
|
||||||
private static class Gate {
|
private static ThreadGroup getRootThreadGroup() {
|
||||||
|
return AccessController.doPrivileged
|
||||||
private boolean exited = false;
|
(new PrivilegedAction<ThreadGroup> () {
|
||||||
private IOException savedException;
|
public ThreadGroup run() {
|
||||||
|
ThreadGroup root = Thread.currentThread().getThreadGroup();
|
||||||
synchronized void exit() { /* Opens the gate */
|
while (root.getParent() != null)
|
||||||
exited = true;
|
root = root.getParent();
|
||||||
this.notify();
|
return root;
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void waitForExit() { /* wait until the gate is open */
|
public Thread newThread(Runnable grimReaper) {
|
||||||
boolean interrupted = false;
|
// Our thread stack requirement is quite modest.
|
||||||
while (!exited) {
|
Thread t = new Thread(group, grimReaper, "process reaper", 32768);
|
||||||
try {
|
t.setDaemon(true);
|
||||||
this.wait();
|
// A small attempt (probably futile) to avoid priority inversion
|
||||||
} catch (InterruptedException e) {
|
t.setPriority(Thread.MAX_PRIORITY);
|
||||||
interrupted = true;
|
return t;
|
||||||
}
|
|
||||||
}
|
|
||||||
if (interrupted) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setException (IOException e) {
|
|
||||||
savedException = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
IOException getException() {
|
|
||||||
return savedException;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The thread pool of "process reaper" daemon threads.
|
||||||
|
*/
|
||||||
|
private static final Executor processReaperExecutor
|
||||||
|
= Executors.newCachedThreadPool(new ProcessReaperThreadFactory());
|
||||||
|
|
||||||
UNIXProcess(final byte[] prog,
|
UNIXProcess(final byte[] prog,
|
||||||
final byte[] argBlock, final int argc,
|
final byte[] argBlock, final int argc,
|
||||||
final byte[] envBlock, final int envc,
|
final byte[] envBlock, final int envc,
|
||||||
final byte[] dir,
|
final byte[] dir,
|
||||||
final int[] std_fds,
|
final int[] fds,
|
||||||
final boolean redirectErrorStream)
|
final boolean redirectErrorStream)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
final Gate gate = new Gate();
|
pid = forkAndExec(prog,
|
||||||
/*
|
argBlock, argc,
|
||||||
* For each subprocess forked a corresponding reaper thread
|
envBlock, envc,
|
||||||
* is started. That thread is the only thread which waits
|
dir,
|
||||||
* for the subprocess to terminate and it doesn't hold any
|
fds,
|
||||||
* locks while doing so. This design allows waitFor() and
|
redirectErrorStream);
|
||||||
* exitStatus() to be safely executed in parallel (and they
|
|
||||||
* need no native code).
|
|
||||||
*/
|
|
||||||
|
|
||||||
java.security.AccessController.doPrivileged(
|
try {
|
||||||
new java.security.PrivilegedAction<Void>() {
|
AccessController.doPrivileged
|
||||||
public Void run() {
|
(new PrivilegedExceptionAction<Void>() {
|
||||||
Thread t = new Thread("process reaper") {
|
public Void run() throws IOException {
|
||||||
public void run() {
|
initStreams(fds);
|
||||||
try {
|
return null;
|
||||||
pid = forkAndExec(prog,
|
}});
|
||||||
argBlock, argc,
|
} catch (PrivilegedActionException ex) {
|
||||||
envBlock, envc,
|
throw (IOException) ex.getException();
|
||||||
dir,
|
}
|
||||||
std_fds,
|
}
|
||||||
redirectErrorStream);
|
|
||||||
} catch (IOException e) {
|
|
||||||
gate.setException(e); /*remember to rethrow later*/
|
|
||||||
gate.exit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
java.security.AccessController.doPrivileged(
|
|
||||||
new java.security.PrivilegedAction<Void>() {
|
|
||||||
public Void run() {
|
|
||||||
if (std_fds[0] == -1)
|
|
||||||
stdin_stream = new ProcessBuilder.NullOutputStream();
|
|
||||||
else {
|
|
||||||
FileDescriptor stdin_fd = new FileDescriptor();
|
|
||||||
fdAccess.set(stdin_fd, std_fds[0]);
|
|
||||||
stdin_stream = new BufferedOutputStream(
|
|
||||||
new FileOutputStream(stdin_fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std_fds[1] == -1)
|
static FileDescriptor newFileDescriptor(int fd) {
|
||||||
stdout_stream = new ProcessBuilder.NullInputStream();
|
FileDescriptor fileDescriptor = new FileDescriptor();
|
||||||
else {
|
fdAccess.set(fileDescriptor, fd);
|
||||||
FileDescriptor stdout_fd = new FileDescriptor();
|
return fileDescriptor;
|
||||||
fdAccess.set(stdout_fd, std_fds[1]);
|
}
|
||||||
stdout_stream = new BufferedInputStream(
|
|
||||||
new FileInputStream(stdout_fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std_fds[2] == -1)
|
void initStreams(int[] fds) throws IOException {
|
||||||
stderr_stream = new ProcessBuilder.NullInputStream();
|
stdin = (fds[0] == -1) ?
|
||||||
else {
|
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||||
FileDescriptor stderr_fd = new FileDescriptor();
|
new ProcessPipeOutputStream(fds[0]);
|
||||||
fdAccess.set(stderr_fd, std_fds[2]);
|
|
||||||
stderr_stream = new FileInputStream(stderr_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; }});
|
stdout = (fds[1] == -1) ?
|
||||||
gate.exit(); /* exit from constructor */
|
ProcessBuilder.NullInputStream.INSTANCE :
|
||||||
int res = waitForProcessExit(pid);
|
new ProcessPipeInputStream(fds[1]);
|
||||||
synchronized (UNIXProcess.this) {
|
|
||||||
hasExited = true;
|
stderr = (fds[2] == -1) ?
|
||||||
exitcode = res;
|
ProcessBuilder.NullInputStream.INSTANCE :
|
||||||
UNIXProcess.this.notifyAll();
|
new ProcessPipeInputStream(fds[2]);
|
||||||
}
|
|
||||||
}
|
processReaperExecutor.execute(new Runnable() {
|
||||||
};
|
public void run() {
|
||||||
t.setDaemon(true);
|
int exitcode = waitForProcessExit(pid);
|
||||||
t.start();
|
UNIXProcess.this.processExited(exitcode);
|
||||||
return null; }});
|
}});
|
||||||
gate.waitForExit();
|
}
|
||||||
IOException e = gate.getException();
|
|
||||||
if (e != null)
|
synchronized void processExited(int exitcode) {
|
||||||
throw new IOException(e.toString());
|
if (stdout instanceof ProcessPipeInputStream)
|
||||||
|
((ProcessPipeInputStream) stdout).processExited();
|
||||||
|
|
||||||
|
if (stderr instanceof ProcessPipeInputStream)
|
||||||
|
((ProcessPipeInputStream) stderr).processExited();
|
||||||
|
|
||||||
|
if (stdin instanceof ProcessPipeOutputStream)
|
||||||
|
((ProcessPipeOutputStream) stdin).processExited();
|
||||||
|
|
||||||
|
this.exitcode = exitcode;
|
||||||
|
hasExited = true;
|
||||||
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
return stdin_stream;
|
return stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
return stdout_stream;
|
return stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getErrorStream() {
|
public InputStream getErrorStream() {
|
||||||
return stderr_stream;
|
return stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int waitFor() throws InterruptedException {
|
public synchronized int waitFor() throws InterruptedException {
|
||||||
@ -228,13 +226,9 @@ final class UNIXProcess extends Process {
|
|||||||
if (!hasExited)
|
if (!hasExited)
|
||||||
destroyProcess(pid);
|
destroyProcess(pid);
|
||||||
}
|
}
|
||||||
try {
|
try { stdin.close(); } catch (IOException ignored) {}
|
||||||
stdin_stream.close();
|
try { stdout.close(); } catch (IOException ignored) {}
|
||||||
stdout_stream.close();
|
try { stderr.close(); } catch (IOException ignored) {}
|
||||||
stderr_stream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This routine initializes JNI field offsets for the class */
|
/* This routine initializes JNI field offsets for the class */
|
||||||
@ -243,4 +237,77 @@ final class UNIXProcess extends Process {
|
|||||||
static {
|
static {
|
||||||
initIDs();
|
initIDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffered input stream for a subprocess pipe file descriptor
|
||||||
|
* that allows the underlying file descriptor to be reclaimed when
|
||||||
|
* the process exits, via the processExited hook.
|
||||||
|
*
|
||||||
|
* This is tricky because we do not want the user-level InputStream to be
|
||||||
|
* closed until the user invokes close(), and we need to continue to be
|
||||||
|
* able to read any buffered data lingering in the OS pipe buffer.
|
||||||
|
*/
|
||||||
|
static class ProcessPipeInputStream extends BufferedInputStream {
|
||||||
|
ProcessPipeInputStream(int fd) {
|
||||||
|
super(new FileInputStream(newFileDescriptor(fd)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] drainInputStream(InputStream in)
|
||||||
|
throws IOException {
|
||||||
|
if (in == null) return null;
|
||||||
|
int n = 0;
|
||||||
|
int j;
|
||||||
|
byte[] a = null;
|
||||||
|
while ((j = in.available()) > 0) {
|
||||||
|
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
|
||||||
|
n += in.read(a, n, j);
|
||||||
|
}
|
||||||
|
return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called by the process reaper thread when the process exits. */
|
||||||
|
synchronized void processExited() {
|
||||||
|
// Most BufferedInputStream methods are synchronized, but close()
|
||||||
|
// is not, and so we have to handle concurrent racing close().
|
||||||
|
try {
|
||||||
|
InputStream in = this.in;
|
||||||
|
if (in != null) {
|
||||||
|
byte[] stragglers = drainInputStream(in);
|
||||||
|
in.close();
|
||||||
|
this.in = (stragglers == null) ?
|
||||||
|
ProcessBuilder.NullInputStream.INSTANCE :
|
||||||
|
new ByteArrayInputStream(stragglers);
|
||||||
|
if (buf == null) // asynchronous close()?
|
||||||
|
this.in = null;
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// probably an asynchronous close().
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffered output stream for a subprocess pipe file descriptor
|
||||||
|
* that allows the underlying file descriptor to be reclaimed when
|
||||||
|
* the process exits, via the processExited hook.
|
||||||
|
*/
|
||||||
|
static class ProcessPipeOutputStream extends BufferedOutputStream {
|
||||||
|
ProcessPipeOutputStream(int fd) {
|
||||||
|
super(new FileOutputStream(newFileDescriptor(fd)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called by the process reaper thread when the process exits. */
|
||||||
|
synchronized void processExited() {
|
||||||
|
OutputStream out = this.out;
|
||||||
|
if (out != null) {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// We know of no reason to get an IOException, but if
|
||||||
|
// we do, there's nothing else to do but carry on.
|
||||||
|
}
|
||||||
|
this.out = ProcessBuilder.NullOutputStream.INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@ public class COMPOUND_TEXT_Encoder extends CharsetEncoder {
|
|||||||
* cannot be used for actual encoding because they are shared across all
|
* cannot be used for actual encoding because they are shared across all
|
||||||
* COMPOUND_TEXT encoders and may be stateful.
|
* COMPOUND_TEXT encoders and may be stateful.
|
||||||
*/
|
*/
|
||||||
private static final Map encodingToEncoderMap =
|
private static final Map<String,CharsetEncoder> encodingToEncoderMap =
|
||||||
Collections.synchronizedMap(new HashMap(21, 1.0f));
|
Collections.synchronizedMap(new HashMap<String,CharsetEncoder>(21, 1.0f));
|
||||||
private static final CharsetEncoder latin1Encoder;
|
private static final CharsetEncoder latin1Encoder;
|
||||||
private static final CharsetEncoder defaultEncoder;
|
private static final CharsetEncoder defaultEncoder;
|
||||||
private static final boolean defaultEncodingSupported;
|
private static final boolean defaultEncodingSupported;
|
||||||
@ -221,7 +221,7 @@ public class COMPOUND_TEXT_Encoder extends CharsetEncoder {
|
|||||||
out.put((byte)0x1B);
|
out.put((byte)0x1B);
|
||||||
out.put((byte)0x25);
|
out.put((byte)0x25);
|
||||||
out.put((byte)0x2F);
|
out.put((byte)0x2F);
|
||||||
out.put((byte)nonStandardBytes[3]);
|
out.put(nonStandardBytes[3]);
|
||||||
|
|
||||||
int toWrite = Math.min(numBytes - nonStandardBytesOff,
|
int toWrite = Math.min(numBytes - nonStandardBytesOff,
|
||||||
(1 << 14) - 1 - nonStandardEncodingLen);
|
(1 << 14) - 1 - nonStandardEncodingLen);
|
||||||
@ -313,12 +313,9 @@ public class COMPOUND_TEXT_Encoder extends CharsetEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. Brute force search of all supported encodings.
|
// 4. Brute force search of all supported encodings.
|
||||||
for (Iterator iter = CompoundTextSupport.getEncodings().iterator();
|
for (String encoding : CompoundTextSupport.getEncodings())
|
||||||
iter.hasNext();)
|
|
||||||
{
|
{
|
||||||
String encoding = (String)iter.next();
|
CharsetEncoder enc = encodingToEncoderMap.get(encoding);
|
||||||
CharsetEncoder enc =
|
|
||||||
(CharsetEncoder)encodingToEncoderMap.get(encoding);
|
|
||||||
if (enc == null) {
|
if (enc == null) {
|
||||||
enc = CompoundTextSupport.getEncoder(encoding);
|
enc = CompoundTextSupport.getEncoder(encoding);
|
||||||
if (enc == null) {
|
if (enc == null) {
|
||||||
|
@ -130,13 +130,13 @@ final class CompoundTextSupport {
|
|||||||
/**
|
/**
|
||||||
* Maps a GL or GR escape sequence to an encoding.
|
* Maps a GL or GR escape sequence to an encoding.
|
||||||
*/
|
*/
|
||||||
private static final Map sequenceToEncodingMap;
|
private static final Map<ControlSequence, String> sequenceToEncodingMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether a particular encoding wants the high bit turned on
|
* Indicates whether a particular encoding wants the high bit turned on
|
||||||
* or off.
|
* or off.
|
||||||
*/
|
*/
|
||||||
private static final Map highBitsMap;
|
private static final Map<ControlSequence, Boolean> highBitsMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps an encoding to an escape sequence. Rather than manage two
|
* Maps an encoding to an escape sequence. Rather than manage two
|
||||||
@ -144,18 +144,21 @@ final class CompoundTextSupport {
|
|||||||
* modify both GL and GR if necessary. This makes the output slightly less
|
* modify both GL and GR if necessary. This makes the output slightly less
|
||||||
* efficient, but our code much simpler.
|
* efficient, but our code much simpler.
|
||||||
*/
|
*/
|
||||||
private static final Map encodingToSequenceMap;
|
private static final Map<String, ControlSequence> encodingToSequenceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keys of 'encodingToSequenceMap', sorted in preferential order.
|
* The keys of 'encodingToSequenceMap', sorted in preferential order.
|
||||||
*/
|
*/
|
||||||
private static final List encodings;
|
private static final List<String> encodings;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
HashMap tSequenceToEncodingMap = new HashMap(33, 1.0f);
|
HashMap<ControlSequence, String> tSequenceToEncodingMap =
|
||||||
HashMap tHighBitsMap = new HashMap(31, 1.0f);
|
new HashMap<>(33, 1.0f);
|
||||||
HashMap tEncodingToSequenceMap = new HashMap(21, 1.0f);
|
HashMap<ControlSequence, Boolean> tHighBitsMap =
|
||||||
ArrayList tEncodings = new ArrayList(21);
|
new HashMap<>(31, 1.0f);
|
||||||
|
HashMap<String, ControlSequence> tEncodingToSequenceMap =
|
||||||
|
new HashMap<>(21, 1.0f);
|
||||||
|
ArrayList<String> tEncodings = new ArrayList<>(21);
|
||||||
|
|
||||||
if (!(isEncodingSupported("US-ASCII") &&
|
if (!(isEncodingSupported("US-ASCII") &&
|
||||||
isEncodingSupported("ISO-8859-1")))
|
isEncodingSupported("ISO-8859-1")))
|
||||||
@ -457,13 +460,12 @@ final class CompoundTextSupport {
|
|||||||
return getNonStandardDecoder(escSequence, null);
|
return getNonStandardDecoder(escSequence, null);
|
||||||
}
|
}
|
||||||
static boolean getHighBit(byte[] escSequence) {
|
static boolean getHighBit(byte[] escSequence) {
|
||||||
Boolean bool = (Boolean)highBitsMap.get
|
Boolean bool = highBitsMap.get(new ControlSequence(escSequence));
|
||||||
(new ControlSequence(escSequence));
|
|
||||||
return (bool == Boolean.TRUE);
|
return (bool == Boolean.TRUE);
|
||||||
}
|
}
|
||||||
static CharsetDecoder getNonStandardDecoder(byte[] escSequence,
|
static CharsetDecoder getNonStandardDecoder(byte[] escSequence,
|
||||||
byte[] encoding) {
|
byte[] encoding) {
|
||||||
return getDecoder((String)sequenceToEncodingMap.get
|
return getDecoder(sequenceToEncodingMap.get
|
||||||
(new ControlSequence(escSequence, encoding)));
|
(new ControlSequence(escSequence, encoding)));
|
||||||
}
|
}
|
||||||
static CharsetDecoder getDecoder(String enc) {
|
static CharsetDecoder getDecoder(String enc) {
|
||||||
@ -474,7 +476,7 @@ final class CompoundTextSupport {
|
|||||||
try {
|
try {
|
||||||
cs = Charset.forName(enc);
|
cs = Charset.forName(enc);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Class cls;
|
Class<?> cls;
|
||||||
try {
|
try {
|
||||||
cls = Class.forName("sun.awt.motif." + enc);
|
cls = Class.forName("sun.awt.motif." + enc);
|
||||||
} catch (ClassNotFoundException ee) {
|
} catch (ClassNotFoundException ee) {
|
||||||
@ -497,22 +499,20 @@ final class CompoundTextSupport {
|
|||||||
|
|
||||||
// For Encoder
|
// For Encoder
|
||||||
static byte[] getEscapeSequence(String encoding) {
|
static byte[] getEscapeSequence(String encoding) {
|
||||||
ControlSequence seq = (ControlSequence)
|
ControlSequence seq = encodingToSequenceMap.get(encoding);
|
||||||
encodingToSequenceMap.get(encoding);
|
|
||||||
if (seq != null) {
|
if (seq != null) {
|
||||||
return seq.escSequence;
|
return seq.escSequence;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
static byte[] getEncoding(String encoding) {
|
static byte[] getEncoding(String encoding) {
|
||||||
ControlSequence seq = (ControlSequence)
|
ControlSequence seq = encodingToSequenceMap.get(encoding);
|
||||||
encodingToSequenceMap.get(encoding);
|
|
||||||
if (seq != null) {
|
if (seq != null) {
|
||||||
return seq.encoding;
|
return seq.encoding;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
static List getEncodings() {
|
static List<String> getEncodings() {
|
||||||
return encodings;
|
return encodings;
|
||||||
}
|
}
|
||||||
static CharsetEncoder getEncoder(String enc) {
|
static CharsetEncoder getEncoder(String enc) {
|
||||||
@ -523,7 +523,7 @@ final class CompoundTextSupport {
|
|||||||
try {
|
try {
|
||||||
cs = Charset.forName(enc);
|
cs = Charset.forName(enc);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Class cls;
|
Class<?> cls;
|
||||||
try {
|
try {
|
||||||
cls = Class.forName("sun.awt.motif." + enc);
|
cls = Class.forName("sun.awt.motif." + enc);
|
||||||
} catch (ClassNotFoundException ee) {
|
} catch (ClassNotFoundException ee) {
|
||||||
|
@ -37,6 +37,7 @@ import static java.lang.ProcessBuilder.Redirect.*;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import static java.lang.System.getenv;
|
import static java.lang.System.getenv;
|
||||||
@ -252,9 +253,9 @@ public class Basic {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print4095(OutputStream s) throws Throwable {
|
static void print4095(OutputStream s, byte b) throws Throwable {
|
||||||
byte[] bytes = new byte[4095];
|
byte[] bytes = new byte[4095];
|
||||||
Arrays.fill(bytes, (byte) '!');
|
Arrays.fill(bytes, b);
|
||||||
s.write(bytes); // Might hang!
|
s.write(bytes); // Might hang!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +274,9 @@ public class Basic {
|
|||||||
public static class JavaChild {
|
public static class JavaChild {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
String action = args[0];
|
String action = args[0];
|
||||||
if (action.equals("testIO")) {
|
if (action.equals("sleep")) {
|
||||||
|
Thread.sleep(10 * 60 * 1000L);
|
||||||
|
} else if (action.equals("testIO")) {
|
||||||
String expected = "standard input";
|
String expected = "standard input";
|
||||||
char[] buf = new char[expected.length()+1];
|
char[] buf = new char[expected.length()+1];
|
||||||
int n = new InputStreamReader(System.in).read(buf,0,buf.length);
|
int n = new InputStreamReader(System.in).read(buf,0,buf.length);
|
||||||
@ -315,7 +318,8 @@ public class Basic {
|
|||||||
printUTF8(new File(System.getProperty("user.dir"))
|
printUTF8(new File(System.getProperty("user.dir"))
|
||||||
.getCanonicalPath());
|
.getCanonicalPath());
|
||||||
} else if (action.equals("print4095")) {
|
} else if (action.equals("print4095")) {
|
||||||
print4095(System.out);
|
print4095(System.out, (byte) '!');
|
||||||
|
print4095(System.err, (byte) 'E');
|
||||||
System.exit(5);
|
System.exit(5);
|
||||||
} else if (action.equals("OutErr")) {
|
} else if (action.equals("OutErr")) {
|
||||||
// You might think the system streams would be
|
// You might think the system streams would be
|
||||||
@ -1717,16 +1721,107 @@ public class Basic {
|
|||||||
} catch (Throwable t) { unexpected(t); }
|
} catch (Throwable t) { unexpected(t); }
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// This would deadlock, if not for the fact that
|
// Attempt to write 4095 bytes to the pipe buffer without a
|
||||||
|
// reader to drain it would deadlock, if not for the fact that
|
||||||
// interprocess pipe buffers are at least 4096 bytes.
|
// interprocess pipe buffers are at least 4096 bytes.
|
||||||
|
//
|
||||||
|
// Also, check that available reports all the bytes expected
|
||||||
|
// in the pipe buffer, and that I/O operations do the expected
|
||||||
|
// things.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
try {
|
try {
|
||||||
List<String> childArgs = new ArrayList<String>(javaChildArgs);
|
List<String> childArgs = new ArrayList<String>(javaChildArgs);
|
||||||
childArgs.add("print4095");
|
childArgs.add("print4095");
|
||||||
Process p = new ProcessBuilder(childArgs).start();
|
final int SIZE = 4095;
|
||||||
print4095(p.getOutputStream()); // Might hang!
|
final Process p = new ProcessBuilder(childArgs).start();
|
||||||
p.waitFor(); // Might hang!
|
print4095(p.getOutputStream(), (byte) '!'); // Might hang!
|
||||||
|
p.waitFor(); // Might hang!
|
||||||
|
equal(SIZE, p.getInputStream().available());
|
||||||
|
equal(SIZE, p.getErrorStream().available());
|
||||||
|
THROWS(IOException.class,
|
||||||
|
new Fun(){void f() throws IOException {
|
||||||
|
p.getOutputStream().write((byte) '!');
|
||||||
|
p.getOutputStream().flush();
|
||||||
|
}});
|
||||||
|
|
||||||
|
final byte[] bytes = new byte[SIZE + 1];
|
||||||
|
equal(SIZE, p.getInputStream().read(bytes));
|
||||||
|
for (int i = 0; i < SIZE; i++)
|
||||||
|
equal((byte) '!', bytes[i]);
|
||||||
|
equal((byte) 0, bytes[SIZE]);
|
||||||
|
|
||||||
|
equal(SIZE, p.getErrorStream().read(bytes));
|
||||||
|
for (int i = 0; i < SIZE; i++)
|
||||||
|
equal((byte) 'E', bytes[i]);
|
||||||
|
equal((byte) 0, bytes[SIZE]);
|
||||||
|
|
||||||
|
equal(0, p.getInputStream().available());
|
||||||
|
equal(0, p.getErrorStream().available());
|
||||||
|
equal(-1, p.getErrorStream().read());
|
||||||
|
equal(-1, p.getInputStream().read());
|
||||||
|
|
||||||
equal(p.exitValue(), 5);
|
equal(p.exitValue(), 5);
|
||||||
|
|
||||||
|
p.getInputStream().close();
|
||||||
|
p.getErrorStream().close();
|
||||||
|
p.getOutputStream().close();
|
||||||
|
|
||||||
|
InputStream[] streams = { p.getInputStream(), p.getErrorStream() };
|
||||||
|
for (final InputStream in : streams) {
|
||||||
|
Fun[] ops = {
|
||||||
|
new Fun(){void f() throws IOException {
|
||||||
|
in.read(); }},
|
||||||
|
new Fun(){void f() throws IOException {
|
||||||
|
in.read(bytes); }},
|
||||||
|
new Fun(){void f() throws IOException {
|
||||||
|
in.available(); }}
|
||||||
|
};
|
||||||
|
for (Fun op : ops) {
|
||||||
|
try {
|
||||||
|
op.f();
|
||||||
|
fail();
|
||||||
|
} catch (IOException expected) {
|
||||||
|
check(expected.getMessage()
|
||||||
|
.matches("[Ss]tream [Cc]losed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable t) { unexpected(t); }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Check that reads which are pending when Process.destroy is
|
||||||
|
// called, get EOF, not IOException("Stream closed").
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
try {
|
||||||
|
final int cases = 4;
|
||||||
|
for (int i = 0; i < cases; i++) {
|
||||||
|
final int action = i;
|
||||||
|
List<String> childArgs = new ArrayList<String>(javaChildArgs);
|
||||||
|
childArgs.add("sleep");
|
||||||
|
final byte[] bytes = new byte[10];
|
||||||
|
final Process p = new ProcessBuilder(childArgs).start();
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
final Thread thread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
latch.countDown();
|
||||||
|
int r;
|
||||||
|
switch (action) {
|
||||||
|
case 0: r = p.getInputStream().read(); break;
|
||||||
|
case 1: r = p.getErrorStream().read(); break;
|
||||||
|
case 2: r = p.getInputStream().read(bytes); break;
|
||||||
|
case 3: r = p.getErrorStream().read(bytes); break;
|
||||||
|
default: throw new Error();
|
||||||
|
}
|
||||||
|
equal(-1, r);
|
||||||
|
} catch (Throwable t) { unexpected(t); }}};
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
latch.await();
|
||||||
|
Thread.sleep(10);
|
||||||
|
p.destroy();
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
} catch (Throwable t) { unexpected(t); }
|
} catch (Throwable t) { unexpected(t); }
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -1741,7 +1836,6 @@ public class Basic {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
new File("./emptyCommand").delete();
|
new File("./emptyCommand").delete();
|
||||||
String m = e.getMessage();
|
String m = e.getMessage();
|
||||||
//e.printStackTrace();
|
|
||||||
if (EnglishUnix.is() &&
|
if (EnglishUnix.is() &&
|
||||||
! matches(m, "Permission denied"))
|
! matches(m, "Permission denied"))
|
||||||
unexpected(e);
|
unexpected(e);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user