LoggerOutputStream bugfix, ParameterizedSocket changes.
ParameterizedSocket ------------------- Moved from transmitting a list of strings (represented by ASCII data separated by ASCII record separators `0x1E`) to a combination of strings and paired strings. Basically, instead of each record being processed as a whole, a record may optionall contain the ASCII unit separator `0x1F`. If it does, the record will be split and treated as a key-value pair. This is implemented in the `ParameterizedSocket.Message` class.o LoggerOutputStream ------------------ Was not initializing the internal buffer.
This commit is contained in:
parent
21cdf6909c
commit
b9fa0d0bbf
@ -1,6 +1,6 @@
|
|||||||
#Wed, 21 Nov 2012 13:12:41 -0600
|
#Thu, 22 Nov 2012 14:39:26 -0600
|
||||||
name=jdb-util
|
name=jdb-util
|
||||||
version=1.7
|
version=1.7
|
||||||
lib.local=true
|
lib.local=true
|
||||||
|
|
||||||
build.number=0
|
build.number=16
|
||||||
|
@ -9,18 +9,44 @@ import java.net.Socket;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class ParameterizedSocket {
|
public class ParameterizedSocket {
|
||||||
|
|
||||||
public static final String START_TOKEN = "\u0001";
|
public static final String START_TOKEN = "\u0001";
|
||||||
public static final String END_TOKEN = "\u0004";
|
public static final String END_TOKEN = "\u0004";
|
||||||
public static final String RECORD_SEPARATOR = "\u001E";
|
public static final String RECORD_SEPARATOR = "\u001E";
|
||||||
|
public static final String FIELD_SEPARATOR = "\u001F";
|
||||||
|
|
||||||
public static final byte START_TOKEN_BYTE = 0x01;
|
public static final byte START_TOKEN_BYTE = 0x01;
|
||||||
public static final byte END_TOKEN_BYTE = 0x04;
|
public static final byte END_TOKEN_BYTE = 0x04;
|
||||||
public static final byte RECORD_SEPARATOR_BYTE = 0x1E;
|
public static final byte RECORD_SEPARATOR_BYTE = 0x1E;
|
||||||
|
public static final byte FIELD_SEPARATOR_BYTE = 0x1F;
|
||||||
|
|
||||||
|
public static class Message {
|
||||||
|
List<String> parts;
|
||||||
|
Map<String, String> namedParameters;
|
||||||
|
|
||||||
|
public Message(List<String> parts, Map<String, String> namedParameters) {
|
||||||
|
this.parts = parts;
|
||||||
|
this.namedParameters = namedParameters; }
|
||||||
|
|
||||||
|
public Message(String... parts) {
|
||||||
|
this.parts = new ArrayList<String>();
|
||||||
|
this.namedParameters = new HashMap<String, String>();
|
||||||
|
|
||||||
|
for (String part : parts) { this.parts.add(part); }}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String part: parts) { sb.append(part + "/"); }
|
||||||
|
for (Map.Entry param : namedParameters.entrySet()) {
|
||||||
|
sb.append(param.getKey() + "=" + param.getValue()); }
|
||||||
|
return sb.toString(); }
|
||||||
|
}
|
||||||
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private Charset charset;
|
private Charset charset;
|
||||||
@ -47,14 +73,15 @@ public class ParameterizedSocket {
|
|||||||
|
|
||||||
public void close() throws IOException { socket.close(); }
|
public void close() throws IOException { socket.close(); }
|
||||||
|
|
||||||
public void writeMessage(String... message) throws IOException {
|
public void writeMessage(Message message) throws IOException {
|
||||||
if (message == null || message.length == 0) return;
|
if (message == null || message.parts.size() == 0) return;
|
||||||
|
|
||||||
byte[] messageBytes = formatMessage(message);
|
byte[] messageBytes = formatMessage(message);
|
||||||
socket.getOutputStream().write(messageBytes); }
|
socket.getOutputStream().write(messageBytes); }
|
||||||
|
|
||||||
public String[] readMessage() throws IOException {
|
public Message readMessage() throws IOException {
|
||||||
List<String> messageList = new ArrayList<String>();
|
List<String> messageList = new ArrayList<String>();
|
||||||
|
Map<String, String> namedParameters = new HashMap<String, String>();
|
||||||
|
|
||||||
if (socket.getInputStream().read() != START_TOKEN_BYTE) {
|
if (socket.getInputStream().read() != START_TOKEN_BYTE) {
|
||||||
byte[] errMsg = formatMessage("ERROR", "Invalid command (expected START_TOKEN).");
|
byte[] errMsg = formatMessage("ERROR", "Invalid command (expected START_TOKEN).");
|
||||||
@ -62,28 +89,69 @@ public class ParameterizedSocket {
|
|||||||
|
|
||||||
int bufIdx= 0;
|
int bufIdx= 0;
|
||||||
int nextByte = socket.getInputStream().read();
|
int nextByte = socket.getInputStream().read();
|
||||||
|
String paramName = null;
|
||||||
|
|
||||||
while (nextByte != END_TOKEN_BYTE) {
|
while (nextByte != END_TOKEN_BYTE) {
|
||||||
|
|
||||||
|
// If we have reached end-of-stream, this is an error.
|
||||||
if (nextByte == -1) {
|
if (nextByte == -1) {
|
||||||
byte[] errMsg = formatMessage("ERROR", "Invalid command: stream ended before END_TOKEN was read.");
|
byte[] errMsg = formatMessage("ERROR", "Invalid command: stream ended before END_TOKEN was read.");
|
||||||
socket.getOutputStream().write(errMsg);
|
socket.getOutputStream().write(errMsg);
|
||||||
return null; }
|
return null; }
|
||||||
|
|
||||||
else if (nextByte == RECORD_SEPARATOR_BYTE) {
|
// Field separator means we have read a parameter name into the
|
||||||
messageList.add(new String(buffer, 0, bufIdx, charset));
|
// buffer.
|
||||||
|
else if (nextByte == FIELD_SEPARATOR_BYTE) {
|
||||||
|
paramName = new String(buffer, 0, bufIdx, charset);
|
||||||
bufIdx = 0; }
|
bufIdx = 0; }
|
||||||
|
|
||||||
|
// Record separator means we have finished reading the current
|
||||||
|
// message part (named or unnamed parameter).
|
||||||
|
else if (nextByte == RECORD_SEPARATOR_BYTE) {
|
||||||
|
|
||||||
|
// No param name, must be an unnamed parameters.
|
||||||
|
if (paramName == null) {
|
||||||
|
messageList.add(new String(buffer, 0, bufIdx, charset));
|
||||||
|
bufIdx = 0; }
|
||||||
|
|
||||||
|
// If we read a param name we know this is a named parameters.
|
||||||
|
else {
|
||||||
|
namedParameters.put(paramName,
|
||||||
|
new String(buffer, 0, bufIdx, charset));
|
||||||
|
bufIdx = 0;
|
||||||
|
paramName = null; } }
|
||||||
|
|
||||||
else { buffer[bufIdx++] = (byte) nextByte; }
|
else { buffer[bufIdx++] = (byte) nextByte; }
|
||||||
|
|
||||||
|
nextByte = socket.getInputStream().read();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bufIdx > 0) messageList.add(new String(buffer, 0, bufIdx, charset));
|
// If we have data in the buffer then there is a remaining parameter
|
||||||
|
// (named or unnamed) to be read.
|
||||||
|
if (bufIdx > 0) {
|
||||||
|
if (paramName == null)
|
||||||
|
messageList.add(new String(buffer, 0, bufIdx, charset));
|
||||||
|
// If we read a param name we know this is a named parameters.
|
||||||
|
else namedParameters.put(paramName,
|
||||||
|
new String(buffer, 0, bufIdx, charset)); }
|
||||||
|
|
||||||
return (String[]) messageList.toArray(); }
|
return new Message(messageList, namedParameters); }
|
||||||
|
|
||||||
|
protected byte[] formatMessage(String... parts) {
|
||||||
|
return formatMessage(new Message(parts)); }
|
||||||
|
|
||||||
|
protected byte[] formatMessage(Message message) {
|
||||||
|
String fullMessage = START_TOKEN + message.parts.get(0);
|
||||||
|
|
||||||
|
// Add all unnamed parameters.
|
||||||
|
for (int i = 1; i < message.parts.size(); i++) {
|
||||||
|
fullMessage += RECORD_SEPARATOR + message.parts.get(i); }
|
||||||
|
|
||||||
|
// Add all named parameters.
|
||||||
|
for (Map.Entry entry : message.namedParameters.entrySet()) {
|
||||||
|
fullMessage += RECORD_SEPARATOR + entry.getKey().toString() +
|
||||||
|
FIELD_SEPARATOR + entry.getValue().toString(); }
|
||||||
|
|
||||||
protected byte[] formatMessage(String... message) {
|
|
||||||
String fullMessage = START_TOKEN + message[0];
|
|
||||||
for (int i = 1; i < message.length; i++) {
|
|
||||||
fullMessage += RECORD_SEPARATOR + message[i]; }
|
|
||||||
fullMessage += END_TOKEN;
|
fullMessage += END_TOKEN;
|
||||||
return fullMessage.getBytes(charset); }
|
return fullMessage.getBytes(charset); }
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
public class LoggerOutputStream {
|
public class LoggerOutputStream extends OutputStream {
|
||||||
|
|
||||||
public enum Level { TRACE, DEBUG, INFO, WARN, ERROR }
|
public enum Level { TRACE, DEBUG, INFO, WARN, ERROR }
|
||||||
|
|
||||||
@ -22,7 +22,8 @@ public class LoggerOutputStream {
|
|||||||
|
|
||||||
public LoggerOutputStream(Logger logger, Level level) {
|
public LoggerOutputStream(Logger logger, Level level) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.level = level; }
|
this.level = level;
|
||||||
|
buffer = new byte[DEFAULT_BUFFER_LENGTH]; }
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void write(final byte[] b, final int offset, final int length)
|
public void write(final byte[] b, final int offset, final int length)
|
||||||
@ -31,15 +32,16 @@ public class LoggerOutputStream {
|
|||||||
throw new IOException("The output stream has been closed.");
|
throw new IOException("The output stream has been closed.");
|
||||||
|
|
||||||
// Grow the buffer if we will reach the limit.
|
// Grow the buffer if we will reach the limit.
|
||||||
if (count + length >= buffer.length) {
|
if ((count + length) >= buffer.length) {
|
||||||
final int newLength =
|
final int newLength =
|
||||||
Math.max(buffer.length + DEFAULT_BUFFER_LENGTH, count + length);
|
Math.max((buffer.length + DEFAULT_BUFFER_LENGTH), (count +
|
||||||
|
length));
|
||||||
final byte[] newBuffer = new byte[newLength];
|
final byte[] newBuffer = new byte[newLength];
|
||||||
|
|
||||||
System.arraycopy(buffer, 0, newBuffer, 0, count);
|
System.arraycopy(buffer, 0, newBuffer, 0, count);
|
||||||
buffer = newBuffer; }
|
buffer = newBuffer; }
|
||||||
|
|
||||||
System.arraycopy(buffer, count, b, offset, length);
|
System.arraycopy(b, count, buffer, offset, length);
|
||||||
count += length;
|
count += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user