/*
* D-Bus Java Implementation Copyright (c) 2005-2006 Matthew Johnson This
* program is free software; you can redistribute it and/or modify it under the
* terms of either the GNU Lesser General Public License Version 2 or the
* Academic Free Licence Version 2.1. Full licence texts are included in the
* COPYING file with this program.
*/
package org.freedesktop.dbus;
import static org.freedesktop.dbus.Gettext._;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.text.MessageFormat;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.MessageProtocolVersionException;
import org.freedesktop.dbus.exceptions.MessageTypeException;
public class MessageReader {
private byte[] body = null;
private byte[] buf = null;
private byte[] header = null;
private InputStream in;
private int[] len = new int[4];
private byte[] tbuf = null;
public MessageReader(InputStream in) {
this.in = new BufferedInputStream(in);
}
public void close() throws IOException {
in.close();
}
public Message readMessage() throws IOException, DBusException {
int rv;
/* Read the 12 byte fixed header, retrying as neccessary */
if (null == buf) {
buf = new byte[12];
len[0] = 0;
}
if (len[0] < 12) {
try {
rv = in.read(buf, len[0], 12 - len[0]);
} catch (SocketTimeoutException STe) {
return null;
}
if (-1 == rv) { throw new EOFException(_("Underlying transport returned EOF")); }
len[0] += rv;
}
if (len[0] == 0) { return null; }
if (len[0] < 12) { return null; }
/* Parse the details from the header */
byte endian = buf[0];
byte type = buf[1];
byte protover = buf[3];
if (protover > Message.PROTOCOL) {
buf = null;
throw new MessageProtocolVersionException(MessageFormat.format(_("Protocol version {0} is unsupported"),
new Object[] { protover }));
}
/* Read the length of the variable header */
if (null == tbuf) {
tbuf = new byte[4];
len[1] = 0;
}
if (len[1] < 4) {
try {
rv = in.read(tbuf, len[1], 4 - len[1]);
} catch (SocketTimeoutException STe) {
return null;
}
if (-1 == rv) { throw new EOFException(_("Underlying transport returned EOF")); }
len[1] += rv;
}
if (len[1] < 4) { return null; }
/* Parse the variable header length */
int headerlen = 0;
if (null == header) {
headerlen = (int) Message.demarshallint(tbuf, 0, endian, 4);
if (0 != headerlen % 8) {
headerlen += 8 - (headerlen % 8);
}
} else {
headerlen = header.length - 8;
}
/* Read the variable header */
if (null == header) {
header = new byte[headerlen + 8];
System.arraycopy(tbuf, 0, header, 0, 4);
len[2] = 0;
}
if (len[2] < headerlen) {
try {
rv = in.read(header, 8 + len[2], headerlen - len[2]);
} catch (SocketTimeoutException STe) {
return null;
}
if (-1 == rv) { throw new EOFException(_("Underlying transport returned EOF")); }
len[2] += rv;
}
if (len[2] < headerlen) { return null; }
/* Read the body */
int bodylen = 0;
if (null == body) {
bodylen = (int) Message.demarshallint(buf, 4, endian, 4);
}
if (null == body) {
body = new byte[bodylen];
len[3] = 0;
}
if (len[3] < body.length) {
try {
rv = in.read(body, len[3], body.length - len[3]);
} catch (SocketTimeoutException STe) {
return null;
}
if (-1 == rv) { throw new EOFException(_("Underlying transport returned EOF")); }
len[3] += rv;
}
if (len[3] < body.length) { return null; }
Message m;
switch (type) {
case Message.MessageType.METHOD_CALL:
m = new MethodCall();
break;
case Message.MessageType.METHOD_RETURN:
m = new MethodReturn();
break;
case Message.MessageType.SIGNAL:
m = new DBusSignal();
break;
case Message.MessageType.ERROR:
m = new Error();
break;
default:
throw new MessageTypeException(MessageFormat.format(_("Message type {0} unsupported"), new Object[] { type }));
}
try {
m.populate(buf, header, body);
} catch (DBusException DBe) {
buf = null;
tbuf = null;
body = null;
header = null;
throw DBe;
} catch (RuntimeException Re) {
buf = null;
tbuf = null;
body = null;
header = null;
throw Re;
}
buf = null;
tbuf = null;
body = null;
header = null;
return m;
}
}
|