XSBuilder.java
import java.text.*; // for NumberFormat
import java.util.regex.*;
// Note workaround for JDK 1.4.0 in XStream constructor.
import com.thoughtworks.xstream.*;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.converters.reflection.
PureJavaReflectionProvider;
/**
Construct or parse XML-formatted network messages. Message format
includes leading length field. Formatting/parsing use the XStream
library (http://xstream.codehaus.org/).
*/
public class XSBuilder implements MsgBuilder
{
protected XStream xstream;
protected Pattern msgHeaderPat;
public XSBuilder()
{
// An XML/object parser...
xstream =
new XStream(
new PureJavaReflectionProvider(),
new DomDriver());
// Recognizes a message header.
msgHeaderPat = Pattern.compile("<<\\d\\d\\d\\d\\d\\d\\d>>");
}
public String makeMessageFromObject(Object obj)
{
String msg = xstream.toXML(obj);
NumberFormat f = NumberFormat.getIntegerInstance();
// Hack to get character count with leading zeroes.
String nstr = "0000000" + f.format(msg.length());
int lstr = nstr.length();
return "<<" + nstr.substring(lstr-7) + ">>" + msg;
}
public Object getMessageFromString(StringBuffer sbuf)
{
if (sbuf.length() < 12)
return null;
Matcher m = msgHeaderPat.matcher(sbuf);
if (m.find()) {
int mlen = m.end() - m.start() + 1;
String s = sbuf.substring(m.start()+2,mlen-3);
int msglen = Integer.parseInt(s);
if (sbuf.length() >= m.start() + msglen + 11) {
String msg =
sbuf.substring(m.start()+11,m.start()+11+msglen);
sbuf.delete(0,m.start()+11+msglen);
Object o = xstream.fromXML(msg);
return o;
}
}
return null;
}
}