summaryrefslogtreecommitdiff
path: root/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java')
-rwxr-xr-xsrc/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java1225
1 files changed, 1225 insertions, 0 deletions
diff --git a/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java
new file mode 100755
index 0000000..269ffab
--- /dev/null
+++ b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Message.java
@@ -0,0 +1,1225 @@
+/*
+ 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.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.io.UnsupportedEncodingException;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import cx.ath.matthew.debug.Debug;
+import cx.ath.matthew.utils.Hexdump;
+
+import org.freedesktop.dbus.exceptions.DBusException;
+import org.freedesktop.dbus.exceptions.MarshallingException;
+import org.freedesktop.dbus.exceptions.UnknownTypeCodeException;
+
+/**
+ * Superclass of all messages which are sent over the Bus.
+ * This class deals with all the marshalling to/from the wire format.
+ */
+public class Message
+{
+ /** Defines constants representing the endianness of the message. */
+ public static interface Endian {
+ public static final byte BIG = 'B';
+ public static final byte LITTLE = 'l';
+ }
+ /** Defines constants representing the flags which can be set on a message. */
+ public static interface Flags {
+ public static final byte NO_REPLY_EXPECTED = 0x01;
+ public static final byte NO_AUTO_START = 0x02;
+ public static final byte ASYNC = 0x40;
+ }
+ /** Defines constants for each message type. */
+ public static interface MessageType {
+ public static final byte METHOD_CALL = 1;
+ public static final byte METHOD_RETURN = 2;
+ public static final byte ERROR = 3;
+ public static final byte SIGNAL = 4;
+ }
+ /** The current protocol major version. */
+ public static final byte PROTOCOL = 1;
+ /** Defines constants for each valid header field type. */
+ public static interface HeaderField {
+ public static final byte PATH = 1;
+ public static final byte INTERFACE = 2;
+ public static final byte MEMBER = 3;
+ public static final byte ERROR_NAME = 4;
+ public static final byte REPLY_SERIAL = 5;
+ public static final byte DESTINATION = 6;
+ public static final byte SENDER = 7;
+ public static final byte SIGNATURE = 8;
+ }
+ /** Defines constants for each argument type.
+ * There are two constants for each argument type,
+ * as a byte or as a String (the _STRING version) */
+ public static interface ArgumentType {
+ public static final String BYTE_STRING="y";
+ public static final String BOOLEAN_STRING="b";
+ public static final String INT16_STRING="n";
+ public static final String UINT16_STRING="q";
+ public static final String INT32_STRING="i";
+ public static final String UINT32_STRING="u";
+ public static final String INT64_STRING="x";
+ public static final String UINT64_STRING="t";
+ public static final String DOUBLE_STRING="d";
+ public static final String FLOAT_STRING="f";
+ public static final String STRING_STRING="s";
+ public static final String OBJECT_PATH_STRING="o";
+ public static final String SIGNATURE_STRING="g";
+ public static final String ARRAY_STRING="a";
+ public static final String VARIANT_STRING="v";
+ public static final String STRUCT_STRING="r";
+ public static final String STRUCT1_STRING="(";
+ public static final String STRUCT2_STRING=")";
+ public static final String DICT_ENTRY_STRING="e";
+ public static final String DICT_ENTRY1_STRING="{";
+ public static final String DICT_ENTRY2_STRING="}";
+
+ public static final byte BYTE='y';
+ public static final byte BOOLEAN='b';
+ public static final byte INT16='n';
+ public static final byte UINT16='q';
+ public static final byte INT32='i';
+ public static final byte UINT32='u';
+ public static final byte INT64='x';
+ public static final byte UINT64='t';
+ public static final byte DOUBLE='d';
+ public static final byte FLOAT='f';
+ public static final byte STRING='s';
+ public static final byte OBJECT_PATH='o';
+ public static final byte SIGNATURE='g';
+ public static final byte ARRAY='a';
+ public static final byte VARIANT='v';
+ public static final byte STRUCT='r';
+ public static final byte STRUCT1='(';
+ public static final byte STRUCT2=')';
+ public static final byte DICT_ENTRY='e';
+ public static final byte DICT_ENTRY1='{';
+ public static final byte DICT_ENTRY2='}';
+ }
+ /** Keep a static reference to each size of padding array to prevent allocation. */
+ private static byte[][] padding;
+ static {
+ padding = new byte[][] {
+ null,
+ new byte[1],
+ new byte[2],
+ new byte[3],
+ new byte[4],
+ new byte[5],
+ new byte[6],
+ new byte[7] };
+ }
+ /** Steps to increment the buffer array. */
+ private static final int BUFFERINCREMENT = 20;
+
+ private boolean big;
+ protected byte[][] wiredata;
+ protected long bytecounter;
+ protected Map<Byte, Object> headers;
+ protected static long globalserial = 0;
+ protected long serial;
+ protected byte type;
+ protected byte flags;
+ protected byte protover;
+ private Object[] args;
+ private byte[] body;
+ private long bodylen = 0;
+ private int preallocated = 0;
+ private int paofs = 0;
+ private byte[] pabuf;
+ private int bufferuse = 0;
+
+ /**
+ * Returns the name of the given header field.
+ */
+ public static String getHeaderFieldName(byte field)
+ {
+ switch (field) {
+ case HeaderField.PATH: return "Path";
+ case HeaderField.INTERFACE: return "Interface";
+ case HeaderField.MEMBER: return "Member";
+ case HeaderField.ERROR_NAME: return "Error Name";
+ case HeaderField.REPLY_SERIAL: return "Reply Serial";
+ case HeaderField.DESTINATION: return "Destination";
+ case HeaderField.SENDER: return "Sender";
+ case HeaderField.SIGNATURE: return "Signature";
+ default: return "Invalid";
+ }
+ }
+
+ /**
+ * Create a message; only to be called by sub-classes.
+ * @param endian The endianness to create the message.
+ * @param type The message type.
+ * @param flags Any message flags.
+ */
+ protected Message(byte endian, byte type, byte flags) throws DBusException
+ {
+ wiredata = new byte[BUFFERINCREMENT][];
+ headers = new HashMap<Byte, Object>();
+ big = (Endian.BIG == endian);
+ bytecounter = 0;
+ synchronized (Message.class) {
+ serial = ++globalserial;
+ }
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Creating message with serial "+serial);
+ this.type = type;
+ this.flags = flags;
+ preallocate(4);
+ append("yyyy", endian, type, flags, Message.PROTOCOL);
+ }
+ /**
+ * Create a blank message. Only to be used when calling populate.
+ */
+ protected Message()
+ {
+ wiredata = new byte[BUFFERINCREMENT][];
+ headers = new HashMap<Byte, Object>();
+ bytecounter = 0;
+ }
+ /**
+ * Create a message from wire-format data.
+ * @param msg D-Bus serialized data of type yyyuu
+ * @param headers D-Bus serialized data of type a(yv)
+ * @param body D-Bus serialized data of the signature defined in headers.
+ */
+ @SuppressWarnings("unchecked")
+ void populate(byte[] msg, byte[] headers, byte[] body) throws DBusException
+ {
+ big = (msg[0] == Endian.BIG);
+ type = msg[1];
+ flags = msg[2];
+ protover = msg[3];
+ wiredata[0] = msg;
+ wiredata[1] = headers;
+ wiredata[2] = body;
+ this.body = body;
+ bufferuse = 3;
+ bodylen = ((Number) extract(Message.ArgumentType.UINT32_STRING, msg, 4)[0]).longValue();
+ serial = ((Number) extract(Message.ArgumentType.UINT32_STRING, msg, 8)[0]).longValue();
+ bytecounter = msg.length+headers.length+body.length;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, headers);
+ Object[] hs = extract("a(yv)", headers, 0);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, Arrays.deepToString(hs));
+ for (Object o: (Vector<Object>) hs[0]) {
+ this.headers.put((Byte) ((Object[])o)[0], ((Variant<Object>)((Object[])o)[1]).getValue());
+ }
+ }
+ /**
+ * Create a buffer of num bytes.
+ * Data is copied to this rather than added to the buffer list.
+ */
+ private void preallocate(int num)
+ {
+ preallocated = 0;
+ pabuf = new byte[num];
+ appendBytes(pabuf);
+ preallocated = num;
+ paofs = 0;
+ }
+ /**
+ * Ensures there are enough free buffers.
+ * @param num number of free buffers to create.
+ */
+ private void ensureBuffers(int num)
+ {
+ int increase = num - wiredata.length + bufferuse;
+ if (increase > 0) {
+ if (increase < BUFFERINCREMENT) increase = BUFFERINCREMENT;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Resizing "+bufferuse);
+ byte[][] temp = new byte[wiredata.length+increase][];
+ System.arraycopy(wiredata, 0, temp, 0, wiredata.length);
+ wiredata = temp;
+ }
+ }
+ /**
+ * Appends a buffer to the buffer list.
+ */
+ protected void appendBytes(byte[] buf)
+ {
+ if (null == buf) return;
+ if (preallocated > 0) {
+ if (paofs+buf.length > pabuf.length)
+ throw new ArrayIndexOutOfBoundsException(MessageFormat.format(_("Array index out of bounds, paofs={0}, pabuf.length={1}, buf.length={2}."), new Object[] { paofs, pabuf.length, buf.length }));
+ System.arraycopy(buf, 0, pabuf, paofs, buf.length);
+ paofs += buf.length;
+ preallocated -= buf.length;
+ } else {
+ if (bufferuse == wiredata.length) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Resizing "+bufferuse);
+ byte[][] temp = new byte[wiredata.length+BUFFERINCREMENT][];
+ System.arraycopy(wiredata, 0, temp, 0, wiredata.length);
+ wiredata = temp;
+ }
+ wiredata[bufferuse++] = buf;
+ bytecounter += buf.length;
+ }
+ }
+ /**
+ * Appends a byte to the buffer list.
+ */
+ protected void appendByte(byte b)
+ {
+ if (preallocated > 0) {
+ pabuf[paofs++] = b;
+ preallocated--;
+ } else {
+ if (bufferuse == wiredata.length) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Resizing "+bufferuse);
+ byte[][] temp = new byte[wiredata.length+BUFFERINCREMENT][];
+ System.arraycopy(wiredata, 0, temp, 0, wiredata.length);
+ wiredata = temp;
+ }
+ wiredata[bufferuse++] = new byte[] { b };
+ bytecounter++;
+ }
+ }
+ /**
+ * Demarshalls an integer of a given width from a buffer.
+ * Endianness is determined from the format of the message.
+ * @param buf The buffer to demarshall from.
+ * @param ofs The offset to demarshall from.
+ * @param width The byte-width of the int.
+ */
+ public long demarshallint(byte[] buf, int ofs, int width)
+ { return big ? demarshallintBig(buf,ofs,width) : demarshallintLittle(buf,ofs,width); }
+ /**
+ * Demarshalls an integer of a given width from a buffer.
+ * @param buf The buffer to demarshall from.
+ * @param ofs The offset to demarshall from.
+ * @param endian The endianness to use in demarshalling.
+ * @param width The byte-width of the int.
+ */
+ public static long demarshallint(byte[] buf, int ofs, byte endian, int width)
+ { return endian==Endian.BIG ? demarshallintBig(buf,ofs,width) : demarshallintLittle(buf,ofs,width); }
+ /**
+ * Demarshalls an integer of a given width from a buffer using big-endian format.
+ * @param buf The buffer to demarshall from.
+ * @param ofs The offset to demarshall from.
+ * @param width The byte-width of the int.
+ */
+ public static long demarshallintBig(byte[] buf, int ofs, int width)
+ {
+ long l = 0;
+ for (int i = 0; i < width; i++) {
+ l <<=8;
+ l |= (buf[ofs+i] & 0xFF);
+ }
+ return l;
+ }
+ /**
+ * Demarshalls an integer of a given width from a buffer using little-endian format.
+ * @param buf The buffer to demarshall from.
+ * @param ofs The offset to demarshall from.
+ * @param width The byte-width of the int.
+ */
+ public static long demarshallintLittle(byte[] buf, int ofs, int width)
+ {
+ long l = 0;
+ for (int i = (width-1); i >= 0; i--) {
+ l <<=8;
+ l |= (buf[ofs+i] & 0xFF);
+ }
+ return l;
+ }
+ /**
+ * Marshalls an integer of a given width and appends it to the message.
+ * Endianness is determined from the message.
+ * @param l The integer to marshall.
+ * @param width The byte-width of the int.
+ */
+ public void appendint(long l, int width)
+ {
+ byte[] buf = new byte[width];
+ marshallint(l, buf, 0, width);
+ appendBytes(buf);
+ }
+ /**
+ * Marshalls an integer of a given width into a buffer.
+ * Endianness is determined from the message.
+ * @param l The integer to marshall.
+ * @param buf The buffer to marshall to.
+ * @param ofs The offset to marshall to.
+ * @param width The byte-width of the int.
+ */
+ public void marshallint(long l, byte[] buf, int ofs, int width)
+ {
+ if (big) marshallintBig(l, buf, ofs, width); else marshallintLittle(l, buf, ofs, width);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Marshalled int "+l+" to "+Hexdump.toHex(buf,ofs,width));
+ }
+ /**
+ * Marshalls an integer of a given width into a buffer using big-endian format.
+ * @param l The integer to marshall.
+ * @param buf The buffer to marshall to.
+ * @param ofs The offset to marshall to.
+ * @param width The byte-width of the int.
+ */
+ public static void marshallintBig(long l, byte[] buf, int ofs, int width)
+ {
+ for (int i = (width-1); i >= 0; i--) {
+ buf[i+ofs] = (byte) (l & 0xFF);
+ l >>= 8;
+ }
+ }
+ /**
+ * Marshalls an integer of a given width into a buffer using little-endian format.
+ * @param l The integer to marshall.
+ * @param buf The buffer to demarshall to.
+ * @param ofs The offset to demarshall to.
+ * @param width The byte-width of the int.
+ */
+ public static void marshallintLittle(long l, byte[] buf, int ofs, int width)
+ {
+ for (int i = 0; i < width; i++) {
+ buf[i+ofs] = (byte) (l & 0xFF);
+ l >>= 8;
+ }
+ }
+ public byte[][] getWireData()
+ {
+ return wiredata;
+ }
+ /**
+ * Formats the message in a human-readable format.
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getSimpleName());
+ sb.append ('(');
+ sb.append (flags);
+ sb.append (',');
+ sb.append(serial);
+ sb.append (')');
+ sb.append (' ');
+ sb.append ('{');
+ sb.append(' ');
+ if (headers.size() == 0)
+ sb.append('}');
+ else {
+ for (Byte field: headers.keySet()) {
+ sb.append(getHeaderFieldName(field));
+ sb.append('=');
+ sb.append('>');
+ sb.append(headers.get(field).toString());
+ sb.append(',');
+ sb.append(' ');
+ }
+ sb.setCharAt(sb.length()-2,' ');
+ sb.setCharAt(sb.length()-1,'}');
+ }
+ sb.append(' ');
+ sb.append('{');
+ sb.append(' ');
+ Object[] args = null;
+ try {
+ args = getParameters();
+ } catch (DBusException DBe) {
+ DBe.printStackTrace(); // pego
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ }
+ if (null == args || 0 == args.length)
+ sb.append('}');
+ else {
+ for (Object o: args) {
+ if (o instanceof Object[])
+ sb.append(Arrays.deepToString((Object[]) o));
+ else if (o instanceof byte[])
+ sb.append(Arrays.toString((byte[]) o));
+ else if (o instanceof int[])
+ sb.append(Arrays.toString((int[]) o));
+ else if (o instanceof short[])
+ sb.append(Arrays.toString((short[]) o));
+ else if (o instanceof long[])
+ sb.append(Arrays.toString((long[]) o));
+ else if (o instanceof boolean[])
+ sb.append(Arrays.toString((boolean[]) o));
+ else if (o instanceof double[])
+ sb.append(Arrays.toString((double[]) o));
+ else if (o instanceof float[])
+ sb.append(Arrays.toString((float[]) o));
+ else
+ if (o != null) { // pego
+ sb.append(o.toString());
+ } else { // pego
+ sb.append("null"); // pego
+ } // pego
+ sb.append(',');
+ sb.append(' ');
+ }
+ sb.setCharAt(sb.length()-2,' ');
+ sb.setCharAt(sb.length()-1,'}');
+ }
+ return sb.toString();
+ }
+ /**
+ * Returns the value of the header field of a given field.
+ * @param type The field to return.
+ * @return The value of the field or null if unset.
+ */
+ public Object getHeader(byte type) { return headers.get(type); }
+ /**
+ * Appends a value to the message.
+ * The type of the value is read from a D-Bus signature and used to marshall
+ * the value.
+ * @param sigb A buffer of the D-Bus signature.
+ * @param sigofs The offset into the signature corresponding to this value.
+ * @param data The value to marshall.
+ * @return The offset into the signature of the end of this value's type.
+ */
+ @SuppressWarnings("unchecked")
+ private int appendone(byte[] sigb, int sigofs, Object data) throws DBusException
+ {
+ try {
+ int i = sigofs;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, (Object) bytecounter);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Appending type: "+((char)sigb[i])+" value: "+data);
+
+ // pad to the alignment of this type.
+ pad(sigb[i]);
+ switch (sigb[i]) {
+ case ArgumentType.BYTE:
+ appendByte(((Number) data).byteValue());
+ break;
+ case ArgumentType.BOOLEAN:
+ appendint(((Boolean) data).booleanValue() ? 1 : 0, 4);
+ break;
+ case ArgumentType.DOUBLE:
+ long l = Double.doubleToLongBits(((Number) data).doubleValue());
+ appendint(l, 8);
+ break;
+ case ArgumentType.FLOAT:
+ int rf = Float.floatToIntBits(((Number) data).floatValue());
+ appendint(rf, 4);
+ break;
+ case ArgumentType.UINT32:
+ appendint(((Number) data).longValue(), 4);
+ break;
+ case ArgumentType.INT64:
+ appendint(((Number) data).longValue(), 8);
+ break;
+ case ArgumentType.UINT64:
+ if (big) {
+ appendint(((UInt64) data).top(), 4);
+ appendint(((UInt64) data).bottom(), 4);
+ } else {
+ appendint(((UInt64) data).bottom(), 4);
+ appendint(((UInt64) data).top(), 4);
+ }
+ break;
+ case ArgumentType.INT32:
+ appendint(((Number) data).intValue(), 4);
+ break;
+ case ArgumentType.UINT16:
+ appendint(((Number) data).intValue(), 2);
+ break;
+ case ArgumentType.INT16:
+ appendint(((Number) data).shortValue(), 2);
+ break;
+ case ArgumentType.STRING:
+ case ArgumentType.OBJECT_PATH:
+ // Strings are marshalled as a UInt32 with the length,
+ // followed by the String, followed by a null byte.
+ String payload = data.toString();
+ byte[] payloadbytes = null;
+ try {
+ payloadbytes = payload.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException UEe) {
+ UEe.printStackTrace(); // pego
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
+ throw new DBusException(_("System does not support UTF-8 encoding"));
+ }
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Appending String of length "+payloadbytes.length);
+ appendint(payloadbytes.length, 4);
+ appendBytes(payloadbytes);
+ appendBytes(padding[1]);
+ //pad(ArgumentType.STRING);? do we need this?
+ break;
+ case ArgumentType.SIGNATURE:
+ // Signatures are marshalled as a byte with the length,
+ // followed by the String, followed by a null byte.
+ // Signatures are generally short, so preallocate the array
+ // for the string, length and null byte.
+ if (data instanceof Type[])
+ payload = Marshalling.getDBusType((Type[]) data);
+ else
+ payload = (String) data;
+ byte[] pbytes = payload.getBytes();
+ preallocate(2+pbytes.length);
+ appendByte((byte) pbytes.length);
+ appendBytes(pbytes);
+ appendByte((byte) 0);
+ break;
+ case ArgumentType.ARRAY:
+ // Arrays are given as a UInt32 for the length in bytes,
+ // padding to the element alignment, then elements in
+ // order. The length is the length from the end of the
+ // initial padding to the end of the last element.
+ if (Debug.debug) {
+ if (data instanceof Object[])
+ Debug.print(Debug.VERBOSE, "Appending array: "+Arrays.deepToString((Object[])data));
+ }
+
+ byte[] alen = new byte[4];
+ appendBytes(alen);
+ pad(sigb[++i]);
+ long c = bytecounter;
+
+ // optimise primatives
+ if (data.getClass().isArray() &&
+ data.getClass().getComponentType().isPrimitive()) {
+ byte[] primbuf;
+ int algn = getAlignment(sigb[i]);
+ int len = Array.getLength(data);
+ switch (sigb[i]) {
+ case ArgumentType.BYTE:
+ primbuf = (byte[]) data;
+ break;
+ case ArgumentType.INT16:
+ case ArgumentType.INT32:
+ case ArgumentType.INT64:
+ primbuf = new byte[len*algn];
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Array.getLong(data, j), primbuf, k, algn);
+ break;
+ case ArgumentType.BOOLEAN:
+ primbuf = new byte[len*algn];
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Array.getBoolean(data, j)?1:0, primbuf, k, algn);
+ break;
+ case ArgumentType.DOUBLE:
+ primbuf = new byte[len*algn];
+ if (data instanceof float[])
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Double.doubleToRawLongBits(((float[])data)[j]),
+ primbuf, k, algn);
+ else
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Double.doubleToRawLongBits(((double[])data)[j]),
+ primbuf, k, algn);
+ break;
+ case ArgumentType.FLOAT:
+ primbuf = new byte[len*algn];
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(
+ Float.floatToRawIntBits(((float[])data)[j]),
+ primbuf, k, algn);
+ break;
+ default:
+ throw new MarshallingException(_("Primative array being sent as non-primative array."));
+ }
+ appendBytes(primbuf);
+ } else if (data instanceof List) {
+ Object[] contents = ((List) data).toArray();
+ int diff = i;
+ ensureBuffers(contents.length*4);
+ for (Object o: contents)
+ diff = appendone(sigb, i, o);
+ i = diff;
+ if (contents.length == 0 && sigb[i] == '(') { // pego In case of zero length array of structs, the 'struct signature' still has to be skipped.
+// System.out.println("PEGO: Going to skip signature for zero sized array.");
+ int nestingLevel = 1;
+ int sigSkipIndex = i;
+ boolean correspondingStruct2Found = false;
+ while (!correspondingStruct2Found) {
+ sigSkipIndex++;
+// System.out.println("PEGO: sigSkipIndex = " + sigSkipIndex + ", byte = " + sigb[sigSkipIndex]);
+ switch (sigb[sigSkipIndex]) {
+ case ArgumentType.STRUCT1:
+ nestingLevel++;
+ break;
+
+ case ArgumentType.STRUCT2:
+ nestingLevel--;
+ if (nestingLevel == 0) {
+ correspondingStruct2Found = true;
+ }
+ break;
+
+ default:
+ // no action
+ }
+ }
+ i = sigSkipIndex;
+// System.out.println("PEGO: setting i to: " + i);
+ }
+ } else if (data instanceof Map) {
+ int diff = i;
+ ensureBuffers(((Map) data).size()*6);
+ for (Map.Entry<Object,Object> o: ((Map<Object,Object>) data).entrySet())
+ diff = appendone(sigb, i, o);
+ if (i == diff) {
+ // advance the type parser even on 0-size arrays.
+ Vector<Type> temp = new Vector<Type>();
+ byte[] temp2 = new byte[sigb.length-diff];
+ System.arraycopy(sigb, diff, temp2, 0, temp2.length);
+ String temp3 = new String(temp2);
+ int temp4 = Marshalling.getJavaType(temp3, temp, 1);
+ diff += temp4;
+ }
+ i = diff;
+ } else {
+ Object[] contents = (Object[]) data;
+ ensureBuffers(contents.length*4);
+ int diff = i;
+ for (Object o: contents)
+ diff = appendone(sigb, i, o);
+ i = diff;
+ }
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "start: "+c+" end: "+bytecounter+" length: "+(bytecounter-c));
+ marshallint(bytecounter-c, alen, 0, 4);
+ break;
+ case ArgumentType.STRUCT1:
+ // Structs are aligned to 8 bytes
+ // and simply contain each element marshalled in order
+ Object[] contents;
+ if (data instanceof Container)
+ contents = ((Container) data).getParameters();
+ else
+ contents = (Object[]) data;
+ ensureBuffers(contents.length*4);
+ int j = 0;
+ for (i++; sigb[i] != ArgumentType.STRUCT2; i++)
+ i = appendone(sigb, i, contents[j++]);
+ break;
+ case ArgumentType.DICT_ENTRY1:
+ // Dict entries are the same as structs.
+ if (data instanceof Map.Entry) {
+ i++;
+ i = appendone(sigb, i, ((Map.Entry) data).getKey());
+ i++;
+ i = appendone(sigb, i, ((Map.Entry) data).getValue());
+ i++;
+ } else {
+ contents = (Object[]) data;
+ j = 0;
+ for (i++; sigb[i] != ArgumentType.DICT_ENTRY2; i++)
+ i = appendone(sigb, i, contents[j++]);
+ }
+ break;
+ case ArgumentType.VARIANT:
+ // Variants are marshalled as a signature
+ // followed by the value.
+ if (data instanceof Variant) {
+ Variant var = (Variant) data;
+ appendone(new byte[] {ArgumentType.SIGNATURE}, 0, var.getSig());
+ appendone((var.getSig()).getBytes(), 0, var.getValue());
+ } else if (data instanceof Object[]) {
+ contents = (Object[]) data;
+ appendone(new byte[] {ArgumentType.SIGNATURE}, 0, contents[0]);
+ appendone(((String) contents[0]).getBytes(), 0, contents[1]);
+ } else {
+ String sig = Marshalling.getDBusType(data.getClass())[0];
+ appendone(new byte[] {ArgumentType.SIGNATURE}, 0, sig);
+ appendone((sig).getBytes(), 0, data);
+ }
+ break;
+ }
+ return i;
+ } catch (ClassCastException CCe) {
+ CCe.printStackTrace(); // pego
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, CCe);
+ throw new MarshallingException(MessageFormat.format(_("Trying to marshall to unconvertable type (from {0} to {1})."), new Object[] { data.getClass().getName(), sigb[sigofs] }));
+ }
+ }
+ /**
+ * Pad the message to the proper alignment for the given type.
+ */
+ public void pad(byte type)
+ {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "padding for "+(char)type);
+ int a = getAlignment(type);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, preallocated+" "+paofs+" "+bytecounter+" "+a);
+ int b = (int) ((bytecounter-preallocated)%a);
+ if (0 == b) return;
+ a = (a-b);
+ if (preallocated > 0) {
+ paofs += a;
+ preallocated -= a;
+ } else
+ appendBytes(padding[a]);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, preallocated+" "+paofs+" "+bytecounter+" "+a);
+ }
+ /**
+ * Return the alignment for a given type.
+ */
+ public static int getAlignment(byte type)
+ {
+ switch (type) {
+ case 2:
+ case ArgumentType.INT16:
+ case ArgumentType.UINT16:
+ return 2;
+ case 4:
+ case ArgumentType.BOOLEAN:
+ case ArgumentType.FLOAT:
+ case ArgumentType.INT32:
+ case ArgumentType.UINT32:
+ case ArgumentType.STRING:
+ case ArgumentType.OBJECT_PATH:
+ case ArgumentType.ARRAY:
+ return 4;
+ case 8:
+ case ArgumentType.INT64:
+ case ArgumentType.UINT64:
+ case ArgumentType.DOUBLE:
+ case ArgumentType.STRUCT:
+ case ArgumentType.DICT_ENTRY:
+ case ArgumentType.STRUCT1:
+ case ArgumentType.DICT_ENTRY1:
+ case ArgumentType.STRUCT2:
+ case ArgumentType.DICT_ENTRY2:
+ return 8;
+ case 1:
+ case ArgumentType.BYTE:
+ case ArgumentType.SIGNATURE:
+ case ArgumentType.VARIANT:
+ default:
+ return 1;
+ }
+ }
+ /**
+ * Append a series of values to the message.
+ * @param sig The signature(s) of the value(s).
+ * @param data The value(s).
+ */
+ public void append(String sig, Object... data) throws DBusException
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Appending sig: "+sig+" data: "+Arrays.deepToString(data));
+ byte[] sigb = sig.getBytes();
+ int j = 0;
+ for (int i = 0; i < sigb.length; i++) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Appending item: "+i+" "+((char)sigb[i])+" "+j);
+ i = appendone(sigb, i, data[j++]);
+ }
+ }
+ /**
+ * Align a counter to the given type.
+ * @param current The current counter.
+ * @param type The type to align to.
+ * @return The new, aligned, counter.
+ */
+ public int align(int current, byte type)
+ {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "aligning to "+(char)type);
+ int a = getAlignment(type);
+ if (0 == (current%a)) return current;
+ return current+(a-(current%a));
+ }
+ /**
+ * Demarshall one value from a buffer.
+ * @param sigb A buffer of the D-Bus signature.
+ * @param buf The buffer to demarshall from. If null, no data will be read.
+ * This can be used to skip a part of the signature only, e.g. in
+ * case of a zero length array. pego
+ * @param ofs An array of two ints, the offset into the signature buffer
+ * and the offset into the data buffer. These values will be
+ * updated to the start of the next value after demarshalling.
+ * @param contained converts nested arrays to Lists
+ * @return The demarshalled value.
+ */
+ private Object extractone(byte[] sigb, byte[] buf, int[] ofs, boolean contained) throws DBusException
+ {
+ if (Debug.debug) Debug.print(Debug.INFO, "Extracting type: "+((char)sigb[ofs[0]])+" from offset "+ofs[1]);
+ Object rv = null;
+ ofs[1] = align(ofs[1], sigb[ofs[0]]);
+ switch (sigb[ofs[0]]) {
+ case ArgumentType.BYTE:
+ if (buf != null) rv = buf[ofs[1]++];
+ break;
+ case ArgumentType.UINT32:
+ if (buf != null) {
+ rv = new UInt32(demarshallint(buf, ofs[1], 4));
+ ofs[1] += 4;
+ }
+ break;
+ case ArgumentType.INT32:
+ if (buf != null) {
+ rv = (int) demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ }
+ break;
+ case ArgumentType.INT16:
+ if (buf != null) {
+ rv = (short) demarshallint(buf, ofs[1], 2);
+ ofs[1] += 2;
+ }
+ break;
+ case ArgumentType.UINT16:
+ if (buf != null) {
+ rv = new UInt16((int) demarshallint(buf, ofs[1], 2));
+ ofs[1] += 2;
+ }
+ break;
+ case ArgumentType.INT64:
+ if (buf != null) {
+ rv = demarshallint(buf, ofs[1], 8);
+ ofs[1] += 8;
+ }
+ break;
+ case ArgumentType.UINT64:
+ if (buf != null) {
+ long top;
+ long bottom;
+ if (big) {
+ top = demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ bottom = demarshallint(buf, ofs[1], 4);
+ } else {
+ bottom = demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ top = demarshallint(buf, ofs[1], 4);
+ }
+ rv = new UInt64(top, bottom);
+ ofs[1] += 4;
+ }
+ break;
+ case ArgumentType.DOUBLE:
+ if (buf != null) {
+ long l = demarshallint(buf, ofs[1], 8);
+ ofs[1] += 8;
+ rv = Double.longBitsToDouble(l);
+ }
+ break;
+ case ArgumentType.FLOAT:
+ if (buf != null) {
+ int rf = (int) demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ rv = Float.intBitsToFloat(rf);
+ }
+ break;
+ case ArgumentType.BOOLEAN:
+ if (buf != null) {
+ int rf = (int) demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ rv = (1==rf)?Boolean.TRUE:Boolean.FALSE;
+ }
+ break;
+ case ArgumentType.ARRAY:
+ if (buf != null) {
+ long size = demarshallint(buf, ofs[1], 4);
+ if (Debug.debug) Debug.print(Debug.INFO, "Reading array of size: "+size);
+ ofs[1] += 4;
+ byte algn = (byte) getAlignment(sigb[++ofs[0]]);
+ ofs[1] = align(ofs[1], sigb[ofs[0]]);
+ int length = (int) (size / algn);
+ if (length > DBusConnection.MAX_ARRAY_LENGTH)
+ throw new MarshallingException(_("Arrays must not exceed ")+DBusConnection.MAX_ARRAY_LENGTH);
+ // optimise primatives
+ switch (sigb[ofs[0]]) {
+ case ArgumentType.BYTE:
+ rv = new byte[length];
+ System.arraycopy(buf, ofs[1], rv, 0, length);
+ ofs[1] += size;
+ break;
+ case ArgumentType.INT16:
+ rv = new short[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((short[]) rv)[j] = (short) demarshallint(buf, ofs[1], algn);
+ break;
+ case ArgumentType.INT32:
+ rv = new int[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((int[]) rv)[j] = (int) demarshallint(buf, ofs[1], algn);
+ break;
+ case ArgumentType.INT64:
+ rv = new long[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((long[]) rv)[j] = demarshallint(buf, ofs[1], algn);
+ break;
+ case ArgumentType.BOOLEAN:
+ rv = new boolean[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((boolean[]) rv)[j] = (1 == demarshallint(buf, ofs[1], algn));
+ break;
+ case ArgumentType.FLOAT:
+ rv = new float[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((float[]) rv)[j] =
+ Float.intBitsToFloat((int)demarshallint(buf, ofs[1], algn));
+ break;
+ case ArgumentType.DOUBLE:
+ rv = new double[length];
+ for (int j = 0; j < length; j++, ofs[1] += algn)
+ ((double[]) rv)[j] =
+ Double.longBitsToDouble(demarshallint(buf, ofs[1], algn));
+ break;
+ case ArgumentType.DICT_ENTRY1:
+// if (0 == size) {
+// // advance the type parser even on 0-size arrays.
+// Vector<Type> temp = new Vector<Type>();
+// byte[] temp2 = new byte[sigb.length-ofs[0]];
+// System.arraycopy(sigb, ofs[0], temp2, 0, temp2.length);
+// String temp3 = new String(temp2);
+// // ofs[0] gets incremented anyway. Leave one character on the stack
+// int temp4 = Marshalling.getJavaType(temp3, temp, 1) - 1;
+// ofs[0] += temp4;
+// if (Debug.debug) Debug.print(Debug.VERBOSE, "Aligned type: "+temp3+" "+temp4+" "+ofs[0]);
+// }
+ Vector<Object[]> entries = new Vector<Object[]>();
+ if (size != 0) {
+ int ofssave = ofs[0];
+ long end = ofs[1]+size;
+ while (ofs[1] < end) {
+ ofs[0] = ofssave;
+ entries.add((Object[]) extractone(sigb, buf, ofs, true));
+ }
+ } else {
+ extractone(sigb, null, ofs, true);
+ }
+ rv = new DBusMap<Object, Object>(entries.toArray(new Object[0][]));
+ break;
+ default:
+// if (0 == size) {
+// // advance the type parser even on 0-size arrays.
+// Vector<Type> temp = new Vector<Type>();
+// byte[] temp2 = new byte[sigb.length-ofs[0]];
+// System.arraycopy(sigb, ofs[0], temp2, 0, temp2.length);
+// String temp3 = new String(temp2);
+// // ofs[0] gets incremented anyway. Leave one character on the stack
+// int temp4 = Marshalling.getJavaType(temp3, temp, 1) - 1;
+// ofs[0] += temp4;
+// if (temp3.startsWith("(")) { // pego
+// ofs[0]--;
+// System.out.println("Zero length array of structs, decrementing ofs[0]");
+// }
+// if (Debug.debug) Debug.print(Debug.VERBOSE, "Aligned type: "+temp3+" "+temp4+" "+ofs[0]);
+// }
+ Vector<Object> contents = new Vector<Object>();
+ if (size != 0) {
+ int ofssave = ofs[0];
+ long end = ofs[1]+size;
+ while (ofs[1] < end) {
+ ofs[0] = ofssave;
+ contents.add(extractone(sigb, buf, ofs, true));
+ }
+ } else {
+ extractone(sigb, null, ofs, true);
+ }
+ rv = contents;
+ }
+ } else {
+ if (Debug.debug) Debug.print(Debug.INFO, "Skipping array");
+ }
+ if (contained && rv != null && !(rv instanceof List) && !(rv instanceof Map))
+ rv = ArrayFrob.listify(rv);
+ break;
+ case ArgumentType.STRUCT1:
+ if (buf != null) {
+ Vector<Object> contents = new Vector<Object>();
+ while (sigb[++ofs[0]] != ArgumentType.STRUCT2)
+ contents.add(extractone(sigb, buf, ofs, true));
+ rv = contents.toArray();
+ } else {
+ while (sigb[++ofs[0]] != ArgumentType.STRUCT2)
+ extractone(sigb, null, ofs, true);
+ }
+ break;
+ case ArgumentType.DICT_ENTRY1:
+ if (buf != null) {
+ Object[] decontents = new Object[2];
+ if (Debug.debug) Debug.print(Debug.INFO, "Extracting Dict Entry ("+Hexdump.toAscii(sigb,ofs[0],sigb.length-ofs[0])+") from: "+Hexdump.toHex(buf,ofs[1],buf.length-ofs[1]));
+ ofs[0]++;
+ decontents[0] = extractone(sigb, buf, ofs, true);
+ ofs[0]++;
+ decontents[1] = extractone(sigb, buf, ofs, true);
+ ofs[0]++;
+ rv = decontents;
+ } else {
+ if (Debug.debug) Debug.print(Debug.INFO, "Skipping Dict Entry ("+Hexdump.toAscii(sigb,ofs[0],sigb.length-ofs[0])+")");
+ ofs[0]++;
+ extractone(sigb, null, ofs, true);
+ ofs[0]++;
+ extractone(sigb, null, ofs, true);
+ ofs[0]++;
+ }
+ break;
+ case ArgumentType.VARIANT:
+ if (buf != null) {
+ int[] newofs = new int[] { 0, ofs[1] };
+ String sig = (String) extract(ArgumentType.SIGNATURE_STRING, buf, newofs)[0];
+ newofs[0] = 0;
+ rv = new Variant<Object>(extract(sig, buf, newofs)[0] , sig);
+ ofs[1] = newofs[1];
+ }
+ break;
+ case ArgumentType.STRING:
+ if (buf != null) {
+ int length = (int) demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ try {
+ rv = new String(buf, ofs[1], length, "UTF-8");
+ } catch (UnsupportedEncodingException UEe) {
+ UEe.printStackTrace(); // pego
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
+ throw new DBusException(_("System does not support UTF-8 encoding"));
+ }
+ ofs[1] += length + 1;
+ }
+ break;
+ case ArgumentType.OBJECT_PATH:
+ if (buf != null) {
+ int length = (int) demarshallint(buf, ofs[1], 4);
+ ofs[1] += 4;
+ rv = new ObjectPath(getSource(), new String(buf, ofs[1], length));
+ ofs[1] += length + 1;
+ }
+ break;
+ case ArgumentType.SIGNATURE:
+ if (buf != null) {
+ int length = (buf[ofs[1]++] & 0xFF);
+ rv = new String(buf, ofs[1], length);
+ ofs[1] += length + 1;
+ }
+ break;
+ default:
+ throw new UnknownTypeCodeException(sigb[ofs[0]]);
+ }
+ if (Debug.debug) if (rv instanceof Object[])
+ Debug.print(Debug.INFO, "Extracted: "+Arrays.deepToString((Object[]) rv)+" (now at "+ofs[1]+")");
+ else
+ Debug.print(Debug.INFO, "Extracted: "+rv+" (now at "+ofs[1]+")");
+ return rv;
+ }
+ /**
+ * Demarshall values from a buffer.
+ * @param sig The D-Bus signature(s) of the value(s).
+ * @param buf The buffer to demarshall from.
+ * @param ofs The offset into the data buffer to start.
+ * @return The demarshalled value(s).
+ */
+ public Object[] extract(String sig, byte[] buf, int ofs) throws DBusException
+ {
+ return extract(sig, buf, new int[] { 0, ofs });
+ }
+ /**
+ * Demarshall values from a buffer.
+ * @param sig The D-Bus signature(s) of the value(s).
+ * @param buf The buffer to demarshall from.
+ * @param ofs An array of two ints, the offset into the signature
+ * and the offset into the data buffer. These values will be
+ * updated to the start of the next value ofter demarshalling.
+ * @return The demarshalled value(s).
+ */
+ public Object[] extract(String sig, byte[] buf, int[] ofs) throws DBusException
+ {
+ if (Debug.debug) Debug.print(Debug.INFO, "extract("+sig+",#"+buf.length+", {"+ofs[0]+","+ofs[1]+"}");
+ Vector<Object> rv = new Vector<Object>();
+ byte[] sigb = sig.getBytes();
+ for (int[] i = ofs; i[0] < sigb.length; i[0]++) {
+ rv.add(extractone(sigb, buf, i, false));
+ }
+ return rv.toArray();
+ }
+ /**
+ * Returns the Bus ID that sent the message.
+ */
+ public String getSource() { return (String) headers.get(HeaderField.SENDER); }
+ /**
+ * Returns the destination of the message.
+ */
+ public String getDestination() { return (String) headers.get(HeaderField.DESTINATION); }
+ /**
+ * Returns the interface of the message.
+ */
+ public String getInterface() { return (String) headers.get(HeaderField.INTERFACE); }
+ /**
+ * Returns the object path of the message.
+ */
+ public String getPath()
+ {
+ Object o = headers.get(HeaderField.PATH);
+ if (null == o) return null;
+ return o.toString();
+ }
+ /**
+ * Returns the member name or error name this message represents.
+ */
+ public String getName()
+ {
+ if (this instanceof Error)
+ return (String) headers.get(HeaderField.ERROR_NAME);
+ else
+ return (String) headers.get(HeaderField.MEMBER);
+ }
+ /**
+ * Returns the dbus signature of the parameters.
+ */
+ public String getSig() { return (String) headers.get(HeaderField.SIGNATURE); }
+ /**
+ * Returns the message flags.
+ */
+ public int getFlags() { return flags; }
+ /**
+ * Returns the message serial ID (unique for this connection)
+ * @return the message serial.
+ */
+ public long getSerial() { return serial; }
+ /**
+ * If this is a reply to a message, this returns its serial.
+ * @return The reply serial, or 0 if it is not a reply.
+ */
+ public long getReplySerial()
+ {
+ Number l = (Number) headers.get(HeaderField.REPLY_SERIAL);
+ if (null == l) return 0;
+ return l.longValue();
+ }
+ /**
+ * Parses and returns the parameters to this message as an Object array.
+ */
+ public Object[] getParameters() throws DBusException
+ {
+ if (null == args && null != body) {
+ String sig = (String) headers.get(HeaderField.SIGNATURE);
+ if (null != sig && 0 != body.length) {
+ args = extract(sig, body, 0);
+ } else args = new Object[0];
+ }
+ return args;
+ }
+ protected void setArgs(Object[] args) { this.args = args; }
+ /**
+ * Warning, do not use this method unless you really know what you are doing.
+ */
+ public void setSource(String source) throws DBusException
+ {
+ if (null != body) {
+ wiredata = new byte[BUFFERINCREMENT][];
+ bufferuse = 0;
+ bytecounter = 0;
+ preallocate(12);
+ append("yyyyuu", big ? Endian.BIG : Endian.LITTLE, type, flags, protover, bodylen, serial);
+ headers.put(HeaderField.SENDER, source);
+ Object[][] newhead = new Object[headers.size()][];
+ int i = 0;
+ for (Byte b: headers.keySet()) {
+ newhead[i] = new Object[2];
+ newhead[i][0] = b;
+ newhead[i][1] = headers.get(b);
+ i++;
+ }
+ append("a(yv)", (Object) newhead);
+ pad((byte) 8);
+ appendBytes(body);
+ }
+ }
+}