use of java.nio.CharBuffer in project Openfire by igniterealtime.
the class XMLLightweightParser method read.
/*
* Main reading method
*/
public void read(IoBuffer byteBuffer) throws Exception {
if (buffer == null) {
// exception was thrown before, avoid duplicate exception(s)
// "read" and discard remaining data
byteBuffer.position(byteBuffer.limit());
return;
}
invalidateBuffer();
// we will abort parsing when 1 Mega of queued chars was found.
if (buffer.length() > maxBufferSize) {
// purge the local buffer / free memory
buffer = null;
// processing the exception takes quite long
final ProtocolDecoderException ex = new ProtocolDecoderException("Stopped parsing never ending stanza");
ex.setHexdump("(redacted hex dump of never ending stanza)");
throw ex;
}
CharBuffer charBuffer = CharBuffer.allocate(byteBuffer.capacity());
encoder.reset();
encoder.decode(byteBuffer.buf(), charBuffer, false);
char[] buf = new char[charBuffer.position()];
charBuffer.flip();
charBuffer.get(buf);
int readChar = buf.length;
// Just return if nothing was read
if (readChar == 0) {
return;
}
buffer.append(buf);
// Robot.
char ch;
boolean isHighSurrogate = false;
for (int i = 0; i < readChar; i++) {
ch = buf[i];
if (ch < 0x20 && ch != 0x9 && ch != 0xA && ch != 0xD && ch != 0x0) {
//Unicode characters in the range 0x0000-0x001F other than 9, A, and D are not allowed in XML
//We need to allow the NULL character, however, for Flash XMLSocket clients to work.
buffer = null;
throw new XMLNotWellFormedException("Character is invalid in: " + ch);
}
if (isHighSurrogate) {
if (Character.isLowSurrogate(ch)) {
// Everything is fine. Clean up traces for surrogates
isHighSurrogate = false;
} else {
// Trigger error. Found high surrogate not followed by low surrogate
buffer = null;
throw new Exception("Found high surrogate not followed by low surrogate");
}
} else if (Character.isHighSurrogate(ch)) {
isHighSurrogate = true;
} else if (Character.isLowSurrogate(ch)) {
// Trigger error. Found low surrogate char without a preceding high surrogate
buffer = null;
throw new Exception("Found low surrogate char without a preceding high surrogate");
}
if (status == XMLLightweightParser.TAIL) {
// Looking for the close tag
if (depth < 1 && ch == head.charAt(tailCount)) {
tailCount++;
if (tailCount == head.length()) {
// Close stanza found!
// Calculate the correct start,end position of the message into the buffer
int end = buffer.length() - readChar + (i + 1);
String msg = buffer.substring(startLastMsg, end);
// Add message to the list
foundMsg(msg);
startLastMsg = end;
}
} else {
tailCount = 0;
status = XMLLightweightParser.INSIDE;
}
} else if (status == XMLLightweightParser.PRETAIL) {
if (ch == XMLLightweightParser.CDATA_START[cdataOffset]) {
cdataOffset++;
if (cdataOffset == XMLLightweightParser.CDATA_START.length) {
status = XMLLightweightParser.INSIDE_CDATA;
cdataOffset = 0;
continue;
}
} else {
cdataOffset = 0;
status = XMLLightweightParser.INSIDE;
}
if (ch == '/') {
status = XMLLightweightParser.TAIL;
depth--;
} else if (ch == '!') {
// This is a <! (comment) so ignore it
status = XMLLightweightParser.INSIDE;
} else {
depth++;
}
} else if (status == XMLLightweightParser.VERIFY_CLOSE_TAG) {
if (ch == '>') {
depth--;
status = XMLLightweightParser.OUTSIDE;
if (depth < 1) {
// Found a tag in the form <tag />
int end = buffer.length() - readChar + (i + 1);
String msg = buffer.substring(startLastMsg, end);
// Add message to the list
foundMsg(msg);
startLastMsg = end;
}
} else if (ch == '<') {
status = XMLLightweightParser.PRETAIL;
insideChildrenTag = true;
} else {
status = XMLLightweightParser.INSIDE;
}
} else if (status == XMLLightweightParser.INSIDE_PARAM_VALUE) {
if (ch == '"') {
status = XMLLightweightParser.INSIDE;
}
} else if (status == XMLLightweightParser.INSIDE_CDATA) {
if (ch == XMLLightweightParser.CDATA_END[cdataOffset]) {
cdataOffset++;
if (cdataOffset == XMLLightweightParser.CDATA_END.length) {
status = XMLLightweightParser.OUTSIDE;
cdataOffset = 0;
}
} else if (cdataOffset == XMLLightweightParser.CDATA_END.length - 1 && ch == XMLLightweightParser.CDATA_END[cdataOffset - 1]) {
// if we are looking for the last CDATA_END char, and we instead found an extra ']'
// char, leave cdataOffset as is and proceed to the next char. This could be a case
// where the XML character data ends with multiple square braces. For Example ]]]>
} else {
cdataOffset = 0;
}
} else if (status == XMLLightweightParser.INSIDE) {
if (ch == XMLLightweightParser.CDATA_START[cdataOffset]) {
cdataOffset++;
if (cdataOffset == XMLLightweightParser.CDATA_START.length) {
status = XMLLightweightParser.INSIDE_CDATA;
cdataOffset = 0;
continue;
}
} else {
cdataOffset = 0;
status = XMLLightweightParser.INSIDE;
}
if (ch == '"') {
status = XMLLightweightParser.INSIDE_PARAM_VALUE;
} else if (ch == '>') {
status = XMLLightweightParser.OUTSIDE;
if (insideRootTag && ("stream:stream>".equals(head.toString()) || ("?xml>".equals(head.toString())) || ("flash:stream>".equals(head.toString())))) {
// Found closing stream:stream
int end = buffer.length() - readChar + (i + 1);
// Skip LF, CR and other "weird" characters that could appear
while (startLastMsg < end && '<' != buffer.charAt(startLastMsg)) {
startLastMsg++;
}
String msg = buffer.substring(startLastMsg, end);
foundMsg(msg);
startLastMsg = end;
}
insideRootTag = false;
} else if (ch == '/') {
status = XMLLightweightParser.VERIFY_CLOSE_TAG;
}
} else if (status == XMLLightweightParser.HEAD) {
if (ch == ' ' || ch == '>') {
// Append > to head to allow searching </tag>
head.append('>');
if (ch == '>')
status = XMLLightweightParser.OUTSIDE;
else
status = XMLLightweightParser.INSIDE;
insideRootTag = true;
insideChildrenTag = false;
continue;
} else if (ch == '/' && head.length() > 0) {
status = XMLLightweightParser.VERIFY_CLOSE_TAG;
depth--;
}
head.append(ch);
} else if (status == XMLLightweightParser.INIT) {
if (ch == '<') {
status = XMLLightweightParser.HEAD;
depth = 1;
} else {
startLastMsg++;
}
} else if (status == XMLLightweightParser.OUTSIDE) {
if (ch == '<') {
status = XMLLightweightParser.PRETAIL;
cdataOffset = 1;
insideChildrenTag = true;
}
}
}
if (head.length() > 0 && ("/stream:stream>".equals(head.toString()) || ("/flash:stream>".equals(head.toString())))) {
// Found closing stream:stream
foundMsg("</stream:stream>");
}
}
use of java.nio.CharBuffer in project hs4j by killme2008.
the class AbstractIoBuffer method getString.
/**
* {@inheritDoc}
*/
@Override
public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException {
checkFieldSize(fieldSize);
if (fieldSize == 0) {
return "";
}
if (!hasRemaining()) {
return "";
}
boolean utf16 = decoder.charset().name().startsWith("UTF-16");
if (utf16 && (fieldSize & 1) != 0) {
throw new IllegalArgumentException("fieldSize is not even.");
}
int oldPos = position();
int oldLimit = limit();
int end = oldPos + fieldSize;
if (oldLimit < end) {
throw new BufferUnderflowException();
}
int i;
if (!utf16) {
for (i = oldPos; i < end; i++) {
if (get(i) == 0) {
break;
}
}
if (i == end) {
limit(end);
} else {
limit(i);
}
} else {
for (i = oldPos; i < end; i += 2) {
if (get(i) == 0 && get(i + 1) == 0) {
break;
}
}
if (i == end) {
limit(end);
} else {
limit(i);
}
}
if (!hasRemaining()) {
limit(oldLimit);
position(end);
return "";
}
decoder.reset();
int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
CharBuffer out = CharBuffer.allocate(expectedLength);
for (; ; ) {
CoderResult cr;
if (hasRemaining()) {
cr = decoder.decode(buf(), out, true);
} else {
cr = decoder.flush(out);
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
out.flip();
o.put(out);
out = o;
continue;
}
if (cr.isError()) {
// Revert the buffer back to the previous state.
limit(oldLimit);
position(oldPos);
cr.throwException();
}
}
limit(oldLimit);
position(end);
return out.flip().toString();
}
use of java.nio.CharBuffer in project hs4j by killme2008.
the class AbstractIoBuffer method putString.
/**
* {@inheritDoc}
*/
@Override
public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException {
checkFieldSize(fieldSize);
if (fieldSize == 0) {
return this;
}
autoExpand(fieldSize);
boolean utf16 = encoder.charset().name().startsWith("UTF-16");
if (utf16 && (fieldSize & 1) != 0) {
throw new IllegalArgumentException("fieldSize is not even.");
}
int oldLimit = limit();
int end = position() + fieldSize;
if (oldLimit < end) {
throw new BufferOverflowException();
}
if (val.length() == 0) {
if (!utf16) {
put((byte) 0x00);
} else {
put((byte) 0x00);
put((byte) 0x00);
}
position(end);
return this;
}
CharBuffer in = CharBuffer.wrap(val);
limit(end);
encoder.reset();
for (; ; ) {
CoderResult cr;
if (in.hasRemaining()) {
cr = encoder.encode(in, buf(), true);
} else {
cr = encoder.flush(buf());
}
if (cr.isUnderflow() || cr.isOverflow()) {
break;
}
cr.throwException();
}
limit(oldLimit);
if (position() < end) {
if (!utf16) {
put((byte) 0x00);
} else {
put((byte) 0x00);
put((byte) 0x00);
}
}
position(end);
return this;
}
use of java.nio.CharBuffer in project hs4j by killme2008.
the class AbstractIoBuffer method putPrefixedString.
/**
* {@inheritDoc}
*/
@Override
public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException {
int maxLength;
switch(prefixLength) {
case 1:
maxLength = 255;
break;
case 2:
maxLength = 65535;
break;
case 4:
maxLength = Integer.MAX_VALUE;
break;
default:
throw new IllegalArgumentException("prefixLength: " + prefixLength);
}
if (val.length() > maxLength) {
throw new IllegalArgumentException("The specified string is too long.");
}
if (val.length() == 0) {
switch(prefixLength) {
case 1:
put((byte) 0);
break;
case 2:
putShort((short) 0);
break;
case 4:
putInt(0);
break;
}
return this;
}
int padMask;
switch(padding) {
case 0:
case 1:
padMask = 0;
break;
case 2:
padMask = 1;
break;
case 4:
padMask = 3;
break;
default:
throw new IllegalArgumentException("padding: " + padding);
}
CharBuffer in = CharBuffer.wrap(val);
// make a room for the length field
skip(prefixLength);
int oldPos = position();
encoder.reset();
int expandedState = 0;
for (; ; ) {
CoderResult cr;
if (in.hasRemaining()) {
cr = encoder.encode(in, buf(), true);
} else {
cr = encoder.flush(buf());
}
if (position() - oldPos > maxLength) {
throw new IllegalArgumentException("The specified string is too long.");
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
if (isAutoExpand()) {
switch(expandedState) {
case 0:
autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar()));
expandedState++;
break;
case 1:
autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()));
expandedState++;
break;
default:
throw new RuntimeException("Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) + " but that wasn't enough for '" + val + "'");
}
continue;
}
} else {
expandedState = 0;
}
cr.throwException();
}
// Write the length field
fill(padValue, padding - (position() - oldPos & padMask));
int length = position() - oldPos;
switch(prefixLength) {
case 1:
put(oldPos - 1, (byte) length);
break;
case 2:
putShort(oldPos - 2, (short) length);
break;
case 4:
putInt(oldPos - 4, length);
break;
}
return this;
}
use of java.nio.CharBuffer in project hs4j by killme2008.
the class AbstractIoBuffer method getPrefixedString.
/**
* Reads a string which has a length field before the actual encoded string,
* using the specified <code>decoder</code> and returns it.
*
* @param prefixLength
* the length of the length field (1, 2, or 4)
* @param decoder
* the decoder to use for decoding the string
* @return the prefixed string
* @throws CharacterCodingException
* when decoding fails
* @throws BufferUnderflowException
* when there is not enough data available
*/
@Override
public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException {
if (!prefixedDataAvailable(prefixLength)) {
throw new BufferUnderflowException();
}
int fieldSize = 0;
switch(prefixLength) {
case 1:
fieldSize = getUnsigned();
break;
case 2:
fieldSize = getUnsignedShort();
break;
case 4:
fieldSize = getInt();
break;
}
if (fieldSize == 0) {
return "";
}
boolean utf16 = decoder.charset().name().startsWith("UTF-16");
if (utf16 && (fieldSize & 1) != 0) {
throw new BufferDataException("fieldSize is not even for a UTF-16 string.");
}
int oldLimit = limit();
int end = position() + fieldSize;
if (oldLimit < end) {
throw new BufferUnderflowException();
}
limit(end);
decoder.reset();
int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
CharBuffer out = CharBuffer.allocate(expectedLength);
for (; ; ) {
CoderResult cr;
if (hasRemaining()) {
cr = decoder.decode(buf(), out, true);
} else {
cr = decoder.flush(out);
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
out.flip();
o.put(out);
out = o;
continue;
}
cr.throwException();
}
limit(oldLimit);
position(end);
return out.flip().toString();
}
Aggregations