diff options
Diffstat (limited to 'src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java')
-rwxr-xr-x | src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java new file mode 100755 index 0000000..b561f19 --- /dev/null +++ b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java @@ -0,0 +1,629 @@ +/* + 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.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +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 org.freedesktop.dbus.exceptions.DBusException; +import org.freedesktop.dbus.types.DBusListType; +import org.freedesktop.dbus.types.DBusMapType; +import org.freedesktop.dbus.types.DBusStructType; + +import cx.ath.matthew.debug.Debug; + +/** + * Contains static methods for marshalling values. + */ +public class Marshalling +{ + private static Map<Type, String[]> typeCache = new HashMap<Type, String[]>(); + /** + * Will return the DBus type corresponding to the given Java type. + * Note, container type should have their ParameterizedType not their + * Class passed in here. + * @param c The Java types. + * @return The DBus types. + * @throws DBusException If the given type cannot be converted to a DBus type. + */ + public static String getDBusType(Type[] c) throws DBusException + { + StringBuffer sb = new StringBuffer(); + for (Type t: c) + for (String s: getDBusType(t)) + sb.append(s); + return sb.toString(); + } + /** + * Will return the DBus type corresponding to the given Java type. + * Note, container type should have their ParameterizedType not their + * Class passed in here. + * @param c The Java type. + * @return The DBus type. + * @throws DBusException If the given type cannot be converted to a DBus type. + */ + public static String[] getDBusType(Type c) throws DBusException + { + String[] cached = typeCache.get(c); + if (null != cached) return cached; + cached = getDBusType(c, false); + typeCache.put(c, cached); + return cached; + } + /** + * Will return the DBus type corresponding to the given Java type. + * Note, container type should have their ParameterizedType not their + * Class passed in here. + * @param c The Java type. + * @param basic If true enforces this to be a non-compound type. (compound types are Maps, Structs and Lists/arrays). + * @return The DBus type. + * @throws DBusException If the given type cannot be converted to a DBus type. + */ + public static String[] getDBusType(Type c, boolean basic) throws DBusException + { + return recursiveGetDBusType(c, basic, 0); + } + private static StringBuffer[] out = new StringBuffer[20]; // pego + @SuppressWarnings("unchecked") + public static String[] recursiveGetDBusType(Type c, boolean basic, int level) throws DBusException + { + if (out.length <= level) { + StringBuffer[] newout = new StringBuffer[out.length]; + System.arraycopy(out, 0, newout, 0, out.length); + out = newout; + } + if (null == out[level]) out[level] = new StringBuffer(); + else out[level].delete(0, out[level].length()); + + if (basic && !(c instanceof Class)) + throw new DBusException(c+_(" is not a basic type")); + + if (c instanceof TypeVariable) out[level].append((char) Message.ArgumentType.VARIANT); + else if (c instanceof GenericArrayType) { + out[level].append((char) Message.ArgumentType.ARRAY); + String[] s = recursiveGetDBusType(((GenericArrayType) c).getGenericComponentType(), false, level+1); + if (s.length != 1) throw new DBusException(_("Multi-valued array types not permitted")); + out[level].append(s[0]); + } else if ((c instanceof Class && + DBusSerializable.class.isAssignableFrom((Class<? extends Object>) c)) || + (c instanceof ParameterizedType && + DBusSerializable.class.isAssignableFrom((Class<? extends Object>) ((ParameterizedType) c).getRawType()))) { + // it's a custom serializable type + Type[] newtypes = null; + if (c instanceof Class) { + for (Method m: ((Class<? extends Object>) c).getDeclaredMethods()) + if (m.getName().equals("deserialize")) + newtypes = m.getGenericParameterTypes(); + } + else + for (Method m: ((Class<? extends Object>) ((ParameterizedType) c).getRawType()).getDeclaredMethods()) + if (m.getName().equals("deserialize")) + newtypes = m.getGenericParameterTypes(); + + if (null == newtypes) throw new DBusException(_("Serializable classes must implement a deserialize method")); + + String[] sigs = new String[newtypes.length]; + for (int j = 0; j < sigs.length; j++) { + String[] ss = recursiveGetDBusType(newtypes[j], false, level+1); + if (1 != ss.length) throw new DBusException(_("Serializable classes must serialize to native DBus types")); + sigs[j] = ss[0]; + } + return sigs; + } + else if (c instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType) c; + if (p.getRawType().equals(Map.class)) { + out[level].append("a{"); + Type[] t = p.getActualTypeArguments(); + try { + String[] s = recursiveGetDBusType(t[0], true, level+1); + if (s.length != 1) throw new DBusException(_("Multi-valued array types not permitted")); + out[level].append(s[0]); + s = recursiveGetDBusType(t[1], false, level+1); + if (s.length != 1) throw new DBusException(_("Multi-valued array types not permitted")); + out[level].append(s[0]); + } catch (ArrayIndexOutOfBoundsException AIOOBe) { + AIOOBe.printStackTrace(); // pego + if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe); + throw new DBusException(_("Map must have 2 parameters")); + } + out[level].append('}'); + } + else if (List.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) { + for (Type t: p.getActualTypeArguments()) { + if (Type.class.equals(t)) + out[level].append((char) Message.ArgumentType.SIGNATURE); + else { + String[] s = recursiveGetDBusType(t, false, level+1); + if (s.length != 1) throw new DBusException(_("Multi-valued array types not permitted")); + out[level].append((char) Message.ArgumentType.ARRAY); + out[level].append(s[0]); + } + } + } + else if (p.getRawType().equals(Variant.class)) { + out[level].append((char) Message.ArgumentType.VARIANT); + } + else if (DBusInterface.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) { + out[level].append((char) Message.ArgumentType.OBJECT_PATH); + } + else if (Tuple.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) { + Type[] ts = p.getActualTypeArguments(); + Vector<String> vs = new Vector<String>(); + for (Type t: ts) + for (String s: recursiveGetDBusType(t, false, level+1)) + vs.add(s); + return vs.toArray(new String[0]); + } + else + throw new DBusException(_("Exporting non-exportable parameterized type ")+c); + } + + else if (c.equals(Byte.class)) out[level].append((char) Message.ArgumentType.BYTE); + else if (c.equals(Byte.TYPE)) out[level].append((char) Message.ArgumentType.BYTE); + else if (c.equals(Boolean.class)) out[level].append((char) Message.ArgumentType.BOOLEAN); + else if (c.equals(Boolean.TYPE)) out[level].append((char) Message.ArgumentType.BOOLEAN); + else if (c.equals(Short.class)) out[level].append((char) Message.ArgumentType.INT16); + else if (c.equals(Short.TYPE)) out[level].append((char) Message.ArgumentType.INT16); + else if (c.equals(UInt16.class)) out[level].append((char) Message.ArgumentType.UINT16); + else if (c.equals(Integer.class)) out[level].append((char) Message.ArgumentType.INT32); + else if (c.equals(Integer.TYPE)) out[level].append((char) Message.ArgumentType.INT32); + else if (c.equals(UInt32.class)) out[level].append((char) Message.ArgumentType.UINT32); + else if (c.equals(Long.class)) out[level].append((char) Message.ArgumentType.INT64); + else if (c.equals(Long.TYPE)) out[level].append((char) Message.ArgumentType.INT64); + else if (c.equals(UInt64.class)) out[level].append((char) Message.ArgumentType.UINT64); + else if (c.equals(Double.class)) out[level].append((char) Message.ArgumentType.DOUBLE); + else if (c.equals(Double.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE); + else if (c.equals(Float.class) && AbstractConnection.FLOAT_SUPPORT) out[level].append((char) Message.ArgumentType.FLOAT); + else if (c.equals(Float.class)) out[level].append((char) Message.ArgumentType.DOUBLE); + else if (c.equals(Float.TYPE) && AbstractConnection.FLOAT_SUPPORT) out[level].append((char) Message.ArgumentType.FLOAT); + else if (c.equals(Float.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE); + else if (c.equals(String.class)) out[level].append((char) Message.ArgumentType.STRING); + else if (c.equals(Variant.class)) out[level].append((char) Message.ArgumentType.VARIANT); + else if (c instanceof Class && + DBusInterface.class.isAssignableFrom((Class<? extends Object>) c)) out[level].append((char) Message.ArgumentType.OBJECT_PATH); + else if (c instanceof Class && + Path.class.equals((Class<? extends Object>) c)) out[level].append((char) Message.ArgumentType.OBJECT_PATH); + else if (c instanceof Class && + ObjectPath.class.equals((Class<? extends Object>) c)) out[level].append((char) Message.ArgumentType.OBJECT_PATH); + else if (c instanceof Class && + ((Class<? extends Object>) c).isArray()) { + if (Type.class.equals(((Class<? extends Object>) c).getComponentType())) + out[level].append((char) Message.ArgumentType.SIGNATURE); + else { + out[level].append((char) Message.ArgumentType.ARRAY); + String[] s = recursiveGetDBusType(((Class<? extends Object>) c).getComponentType(), false, level+1); + if (s.length != 1) throw new DBusException(_("Multi-valued array types not permitted")); + out[level].append(s[0]); + } + } else if (c instanceof Class && + Struct.class.isAssignableFrom((Class<? extends Object>) c)) { + out[level].append((char) Message.ArgumentType.STRUCT1); + Type[] ts = Container.getTypeCache(c); + if (null == ts) { + Field[] fs = ((Class<? extends Object>) c).getDeclaredFields(); + ts = new Type[fs.length]; + for (Field f : fs) { + Position p = f.getAnnotation(Position.class); + if (null == p) continue; + ts[p.value()] = f.getGenericType(); + } + Container.putTypeCache(c, ts); + } + + for (Type t: ts) + if (t != null) + for (String s: recursiveGetDBusType(t, false, level+1)) + out[level].append(s); + out[level].append(')'); + } else { + throw new DBusException(_("Exporting non-exportable type ")+c); + } + + if (Debug.debug) Debug.print(Debug.VERBOSE, "Converted Java type: "+c+" to D-Bus Type: "+out[level]); + + return new String[] { out[level].toString() }; + } + + /** + * Converts a dbus type string into Java Type objects, + * @param dbus The DBus type or types. + * @param rv Vector to return the types in. + * @param limit Maximum number of types to parse (-1 == nolimit). + * @return number of characters parsed from the type string. + */ + public static int getJavaType(String dbus, List<Type> rv, int limit) throws DBusException + { + if (null == dbus || "".equals(dbus) || 0 == limit) return 0; + + try { + int i = 0; + for (; i < dbus.length() && (-1 == limit || limit > rv.size()); i++) + switch(dbus.charAt(i)) { + case Message.ArgumentType.STRUCT1: + int j = i+1; + for (int c = 1; c > 0; j++) { + if (')' == dbus.charAt(j)) c--; + else if (Message.ArgumentType.STRUCT1 == dbus.charAt(j)) c++; + } + + Vector<Type> contained = new Vector<Type>(); + int c = getJavaType(dbus.substring(i+1, j-1), contained, -1); + rv.add(new DBusStructType(contained.toArray(new Type[0]))); + i = j; + break; + case Message.ArgumentType.ARRAY: + if (Message.ArgumentType.DICT_ENTRY1 == dbus.charAt(i+1)) { + contained = new Vector<Type>(); + c = getJavaType(dbus.substring(i+2), contained, 2); + rv.add(new DBusMapType(contained.get(0), contained.get(1))); + i += (c+2); + } else { + contained = new Vector<Type>(); + c = getJavaType(dbus.substring(i+1), contained, 1); + rv.add(new DBusListType(contained.get(0))); + i += c; + } + break; + case Message.ArgumentType.VARIANT: + rv.add(Variant.class); + break; + case Message.ArgumentType.BOOLEAN: + rv.add(Boolean.class); + break; + case Message.ArgumentType.INT16: + rv.add(Short.class); + break; + case Message.ArgumentType.BYTE: + rv.add(Byte.class); + break; + case Message.ArgumentType.OBJECT_PATH: + rv.add(DBusInterface.class); + break; + case Message.ArgumentType.UINT16: + rv.add(UInt16.class); + break; + case Message.ArgumentType.INT32: + rv.add(Integer.class); + break; + case Message.ArgumentType.UINT32: + rv.add(UInt32.class); + break; + case Message.ArgumentType.INT64: + rv.add(Long.class); + break; + case Message.ArgumentType.UINT64: + rv.add(UInt64.class); + break; + case Message.ArgumentType.DOUBLE: + rv.add(Double.class); + break; + case Message.ArgumentType.FLOAT: + rv.add(Float.class); + break; + case Message.ArgumentType.STRING: + rv.add(String.class); + break; + case Message.ArgumentType.SIGNATURE: + rv.add(Type[].class); + break; + case Message.ArgumentType.DICT_ENTRY1: + rv.add(Map.Entry.class); + contained = new Vector<Type>(); + c = getJavaType(dbus.substring(i+1), contained, 2); + i+=c+1; + break; + default: + throw new DBusException(MessageFormat.format(_("Failed to parse DBus type signature: {0} ({1})."), new Object[] { dbus, dbus.charAt(i) })); + } + return i; + } catch (IndexOutOfBoundsException IOOBe) { + IOOBe.printStackTrace(); // pego + if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOOBe); + throw new DBusException(_("Failed to parse DBus type signature: ")+dbus); + } + } + /** + * Recursively converts types for serialization onto DBus. + * @param parameters The parameters to convert. + * @param types The (possibly generic) types of the parameters. + * @return The converted parameters. + * @throws DBusException Thrown if there is an error in converting the objects. + */ + @SuppressWarnings("unchecked") + public static Object[] convertParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws DBusException + { + if (null == parameters) return null; + for (int i = 0; i < parameters.length; i++) { + if (Debug.debug) Debug.print(Debug.VERBOSE,"Converting "+i+" from "+parameters[i]+" to "+types[i]); + if (null == parameters[i]) continue; + + if (parameters[i] instanceof DBusSerializable) { + for (Method m: parameters[i].getClass().getDeclaredMethods()) + if (m.getName().equals("deserialize")) { + Type[] newtypes = m.getParameterTypes(); + Type[] expand = new Type[types.length + newtypes.length - 1]; + System.arraycopy(types, 0, expand, 0, i); + System.arraycopy(newtypes, 0, expand, i, newtypes.length); + System.arraycopy(types, i+1, expand, i+newtypes.length, types.length-i-1); + types = expand; + Object[] newparams = ((DBusSerializable) parameters[i]).serialize(); + Object[] exparams = new Object[parameters.length + newparams.length - 1]; + System.arraycopy(parameters, 0, exparams, 0, i); + System.arraycopy(newparams, 0, exparams, i, newparams.length); + System.arraycopy(parameters, i+1, exparams, i+newparams.length, parameters.length-i-1); + parameters = exparams; + } + i--; + } else if (parameters[i] instanceof Tuple) { + Type[] newtypes = ((ParameterizedType) types[i]).getActualTypeArguments(); + Type[] expand = new Type[types.length + newtypes.length - 1]; + System.arraycopy(types, 0, expand, 0, i); + System.arraycopy(newtypes, 0, expand, i, newtypes.length); + System.arraycopy(types, i+1, expand, i+newtypes.length, types. length-i-1); + types = expand; + Object[] newparams = ((Tuple) parameters[i]).getParameters(); + Object[] exparams = new Object[parameters.length + newparams.length - 1]; + System.arraycopy(parameters, 0, exparams, 0, i); + System.arraycopy(newparams, 0, exparams, i, newparams.length); + System.arraycopy(parameters, i+1, exparams, i+newparams.length, parameters.length-i-1); + parameters = exparams; + if (Debug.debug) Debug.print(Debug.VERBOSE, "New params: "+Arrays.deepToString(parameters)+" new types: "+Arrays.deepToString(types)); + i--; + } else if (types[i] instanceof TypeVariable && + !(parameters[i] instanceof Variant)) + // its an unwrapped variant, wrap it + parameters[i] = new Variant<Object>(parameters[i]); + else if (parameters[i] instanceof DBusInterface) + parameters[i] = conn.getExportedObject((DBusInterface) parameters[i]); + } + return parameters; + } + @SuppressWarnings("unchecked") + static Object deSerializeParameter(Object parameter, Type type, AbstractConnection conn) throws Exception + { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing from "+parameter.getClass()+" to "+type.getClass()); + if (null == parameter) + return null; + + // its a wrapped variant, unwrap it + if (type instanceof TypeVariable + && parameter instanceof Variant) { + parameter = ((Variant)parameter).getValue(); + } + + // Turn a signature into a Type[] + if (type instanceof Class + && ((Class) type).isArray() + && ((Class) type).getComponentType().equals(Type.class) + && parameter instanceof String) { + Vector<Type> rv = new Vector<Type>(); + getJavaType((String) parameter, rv, -1); + parameter = rv.toArray(new Type[0]); + } + + // its an object path, get/create the proxy + if (parameter instanceof ObjectPath) { + if (type instanceof Class && DBusInterface.class.isAssignableFrom((Class) type)) + parameter = conn.getExportedObject( + ((ObjectPath) parameter).source, + ((ObjectPath) parameter).path); + else + parameter = new Path(((ObjectPath) parameter).path); + } + + // it should be a struct. create it + if (parameter instanceof Object[] && + type instanceof Class && + Struct.class.isAssignableFrom((Class) type)) { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Creating Struct "+type+" from "+parameter); + Type[] ts = Container.getTypeCache(type); + if (null == ts) { + Field[] fs = ((Class) type).getDeclaredFields(); + ts = new Type[fs.length]; + for (Field f : fs) { + Position p = f.getAnnotation(Position.class); + if (null == p) continue; + ts[p.value()] = f.getGenericType(); + } + Container.putTypeCache(type, ts); + } + + // recurse over struct contents + parameter = deSerializeParameters((Object[]) parameter, ts, conn); + for (Constructor con: ((Class) type).getDeclaredConstructors()) { + try { + parameter = con.newInstance((Object[]) parameter); + break; + } catch (IllegalArgumentException IAe) {} + } + } + + // recurse over arrays + if (parameter instanceof Object[]) { + Type[] ts = new Type[((Object[]) parameter).length]; + Arrays.fill(ts, parameter.getClass().getComponentType()); + parameter = deSerializeParameters((Object[]) parameter, + ts, conn); + } + if (parameter instanceof List) { + Type type2; + if (type instanceof ParameterizedType) + type2 = ((ParameterizedType) type).getActualTypeArguments()[0]; + else if (type instanceof GenericArrayType) + type2 = ((GenericArrayType) type).getGenericComponentType(); + else if (type instanceof Class && ((Class) type).isArray()) + type2 = ((Class) type).getComponentType(); + else + type2 = null; + if (null != type2) + parameter = deSerializeParameters((List) parameter, type2, conn); + } + + // correct floats if appropriate + if (type.equals(Float.class) || type.equals(Float.TYPE)) + if (!(parameter instanceof Float)) + parameter = ((Number) parameter).floatValue(); + + // make sure arrays are in the correct format + if (parameter instanceof Object[] || + parameter instanceof List || + parameter.getClass().isArray()) { + if (type instanceof ParameterizedType) + parameter = ArrayFrob.convert(parameter, + (Class<? extends Object>) ((ParameterizedType) type).getRawType()); + else if (type instanceof GenericArrayType) { + Type ct = ((GenericArrayType) type).getGenericComponentType(); + Class cc = null; + if (ct instanceof Class) + cc = (Class) ct; + if (ct instanceof ParameterizedType) + cc = (Class) ((ParameterizedType) ct).getRawType(); + Object o = Array.newInstance(cc, 0); + parameter = ArrayFrob.convert(parameter, + o.getClass()); + } else if (type instanceof Class && + ((Class) type).isArray()) { + Class cc = ((Class) type).getComponentType(); + if ((cc.equals(Float.class) || cc.equals(Float.TYPE)) + && (parameter instanceof double[])) { + double[] tmp1 = (double[]) parameter; + float[] tmp2 = new float[tmp1.length]; + for (int i = 0; i < tmp1.length; i++) + tmp2[i] = (float) tmp1[i]; + parameter = tmp2; + } + Object o = Array.newInstance(cc, 0); + parameter = ArrayFrob.convert(parameter, + o.getClass()); + } + } + if (parameter instanceof DBusMap) { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing a Map"); + DBusMap dmap = (DBusMap) parameter; + Type[] maptypes = ((ParameterizedType) type).getActualTypeArguments(); + for (int i = 0; i < dmap.entries.length; i++) { + dmap.entries[i][0] = deSerializeParameter(dmap.entries[i][0], maptypes[0], conn); + dmap.entries[i][1] = deSerializeParameter(dmap.entries[i][1], maptypes[1], conn); + } + } + return parameter; + } + static List<Object> deSerializeParameters(List<Object> parameters, Type type, AbstractConnection conn) throws Exception + { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing from "+parameters+" to "+type); + if (null == parameters) return null; + for (int i = 0; i < parameters.size(); i++) { + if (null == parameters.get(i)) continue; + + /* DO NOT DO THIS! IT'S REALLY NOT SUPPORTED! + * if (type instanceof Class && + DBusSerializable.class.isAssignableFrom((Class) types[i])) { + for (Method m: ((Class) types[i]).getDeclaredMethods()) + if (m.getName().equals("deserialize")) { + Type[] newtypes = m.getGenericParameterTypes(); + try { + Object[] sub = new Object[newtypes.length]; + System.arraycopy(parameters, i, sub, 0, newtypes.length); + sub = deSerializeParameters(sub, newtypes, conn); + DBusSerializable sz = (DBusSerializable) ((Class) types[i]).newInstance(); + m.invoke(sz, sub); + Object[] compress = new Object[parameters.length - newtypes.length + 1]; + System.arraycopy(parameters, 0, compress, 0, i); + compress[i] = sz; + System.arraycopy(parameters, i + newtypes.length, compress, i+1, parameters.length - i - newtypes.length); + parameters = compress; + } catch (ArrayIndexOutOfBoundsException AIOOBe) { + if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe); + throw new DBusException("Not enough elements to create custom object from serialized data ("+(parameters.size()-i)+" < "+(newtypes.length)+")"); + } + } + } else*/ + parameters.set(i, deSerializeParameter(parameters.get(i), type, conn)); + } + return parameters; + } + + @SuppressWarnings("unchecked") + static Object[] deSerializeParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws Exception + { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing from "+Arrays.deepToString(parameters)+" to "+Arrays.deepToString(types)); + if (null == parameters) return null; + + if (types.length == 1 && types[0] instanceof ParameterizedType + && Tuple.class.isAssignableFrom((Class) ((ParameterizedType) types[0]).getRawType())) { + types = ((ParameterizedType) types[0]).getActualTypeArguments(); + } + + for (int i = 0; i < parameters.length; i++) { + // CHECK IF ARRAYS HAVE THE SAME LENGTH <-- has to happen after expanding parameters + if (i >= types.length) { + if (Debug.debug) { + for (int j = 0; j < parameters.length; j++) { + Debug.print(Debug.ERR, String.format("Error, Parameters difference (%1d, '%2s')", j, parameters[j].toString())); + } + } + throw new DBusException(_("Error deserializing message: number of parameters didn't match receiving signature")); + } + if (null == parameters[i]) continue; + + if ((types[i] instanceof Class && + DBusSerializable.class.isAssignableFrom((Class<? extends Object>) types[i])) || + (types[i] instanceof ParameterizedType && + DBusSerializable.class.isAssignableFrom((Class<? extends Object>) ((ParameterizedType) types[i]).getRawType()))) { + Class<? extends DBusSerializable> dsc; + if (types[i] instanceof Class) + dsc = (Class<? extends DBusSerializable>) types[i]; + else + dsc = (Class<? extends DBusSerializable>) ((ParameterizedType) types[i]).getRawType(); + for (Method m: dsc.getDeclaredMethods()) + if (m.getName().equals("deserialize")) { + Type[] newtypes = m.getGenericParameterTypes(); + try { + Object[] sub = new Object[newtypes.length]; + System.arraycopy(parameters, i, sub, 0, newtypes.length); + sub = deSerializeParameters(sub, newtypes, conn); + DBusSerializable sz = dsc.newInstance(); + m.invoke(sz, sub); + Object[] compress = new Object[parameters.length - newtypes.length + 1]; + System.arraycopy(parameters, 0, compress, 0, i); + compress[i] = sz; + System.arraycopy(parameters, i + newtypes.length, compress, i+1, parameters.length - i - newtypes.length); + parameters = compress; + } catch (ArrayIndexOutOfBoundsException AIOOBe) { + AIOOBe.printStackTrace(); // pego + if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe); + throw new DBusException(MessageFormat.format(_("Not enough elements to create custom object from serialized data ({0} < {1})."), + new Object[] { parameters.length-i, newtypes.length })); + } + } + } else + parameters[i] = deSerializeParameter(parameters[i], types[i], conn); + } + return parameters; + } +} + + |