if (DBusConnection.EXCEPTION_DEBUG) AIOOBe.printStackTrace();
   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);      }      if (null == out[level]) out[level] = new StringBuffer();      else out[level].delete(0, out.length);            if (basic && !(c instanceof Class))         throw new DBusException(c+" is not a basic type");      if (c instanceof TypeVariable) out[level].append('v');      else if (c instanceof GenericArrayType) {         out[level].append('a');         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 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) {               throw new DBusException("Map must have 2 parameters");            }            out[level].append('}');         }         else if (List.class.isAssignableFrom((Class) p.getRawType())) {            out[level].append('a');            for (Type t: p.getActualTypeArguments()) {               String[] s = recursiveGetDBusType(t, false, level+1);               if (s.length != 1) throw new DBusException("Multi-valued array types not permitted");               out[level].append(s[0]);            }         }          else if (p.getRawType().equals(Variant.class)) {            out[level].append('v');         }         else if (DBusInterface.class.isAssignableFrom((Class) p.getRawType())) {            out[level].append('o');         }         else            throw new DBusException("Exporting non-exportable parameterized type "+c);      }            else if (c.equals(Byte.class)) out[level].append('y');      else if (c.equals(Byte.TYPE)) out[level].append('y');      else if (c.equals(Boolean.class)) out[level].append('b');      else if (c.equals(Boolean.TYPE)) out[level].append('b');      else if (c.equals(Short.class)) out[level].append('n');      else if (c.equals(Short.TYPE)) out[level].append('n');      else if (c.equals(UInt16.class)) out[level].append('q');      else if (c.equals(Integer.class)) out[level].append('i');      else if (c.equals(Integer.TYPE)) out[level].append('i');      else if (c.equals(UInt32.class)) out[level].append('u');      else if (c.equals(Long.class)) out[level].append('x');      else if (c.equals(Long.TYPE)) out[level].append('x');      else if (c.equals(UInt64.class)) out[level].append('t');      else if (c.equals(Double.class)) out[level].append('d');      else if (c.equals(Double.TYPE)) out[level].append('d');      else if (c.equals(String.class)) out[level].append('s');      else if (c.equals(Variant.class)) out[level].append('v');      else if (c instanceof Class &&             DBusInterface.class.isAssignableFrom((Class) c)) out[level].append('o');      else if (c instanceof Class && ((Class) c).isArray()) {         out[level].append('a');         String[] s = recursiveGetDBusType(((Class) 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) c)) {         out[level].append('(');         Type[] ts = Struct.getStructTypeCache(c);         if (null == ts) {            Field[] fs = ((Class) 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();           }            Struct.putStructTypeCache(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 if ((c instanceof Class &&             DBusSerializable.class.isAssignableFrom((Class) c)) ||            (c instanceof ParameterizedType &&             DBusSerializable.class.isAssignableFrom((Class) ((ParameterizedType) c).getRawType()))) {         // it's a custom serializable type         Type[] newtypes = null;         if (c instanceof Class)  {            for (Method m: ((Class) c).getDeclaredMethods())                if (m.getName().equals("deserialize"))                   newtypes = m.getGenericParameterTypes();         }         else             for (Method m: ((Class) ((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 {         throw new DBusException("Exporting non-exportable type "+c);      }      return new String[] { out[level].toString() };   }