
org.freedesktop.dbus.Marshalling Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dbus-java-osgi Show documentation
Show all versions of dbus-java-osgi Show documentation
Improved version of the DBus-Java library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/).
This is the OSGi compliant bundle of all required libraries in one bundle.
The newest version!
package org.freedesktop.dbus;
import org.freedesktop.dbus.annotations.Position;
import org.freedesktop.dbus.connections.AbstractConnection;
import org.freedesktop.dbus.connections.base.AbstractConnectionBase;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.DBusTypeConversationRuntimeException;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.interfaces.DBusSerializable;
import org.freedesktop.dbus.messages.constants.ArgumentType;
import org.freedesktop.dbus.types.*;
import org.freedesktop.dbus.utils.LoggingHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
/**
* Contains static methods for marshalling values.
*/
public final class Marshalling {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
/** Used as initial and incremental size of StringBuffer array when resolving DBusTypes recursively. */
private static final int INITIAL_BUFFER_SZ = 10;
private static final String MTH_NAME_DESERIALIZE = "deserialize";
private static final String ERROR_MULTI_VALUED_ARRAY = "Multi-valued array types not permitted";
private static final Logger LOGGER = LoggerFactory.getLogger(Marshalling.class);
private static final Map TYPE_CACHE = new ConcurrentHashMap<>();
private static final Map, Byte> CLASS_TO_ARGUMENTTYPE = new LinkedHashMap<>();
static {
CLASS_TO_ARGUMENTTYPE.put(Boolean.class, ArgumentType.BOOLEAN); // class
CLASS_TO_ARGUMENTTYPE.put(Boolean.TYPE, ArgumentType.BOOLEAN); // primitive type
CLASS_TO_ARGUMENTTYPE.put(Byte.class, ArgumentType.BYTE);
CLASS_TO_ARGUMENTTYPE.put(Byte.TYPE, ArgumentType.BYTE);
CLASS_TO_ARGUMENTTYPE.put(Short.class, ArgumentType.INT16);
CLASS_TO_ARGUMENTTYPE.put(Short.TYPE, ArgumentType.INT16);
CLASS_TO_ARGUMENTTYPE.put(Integer.class, ArgumentType.INT32);
CLASS_TO_ARGUMENTTYPE.put(Integer.TYPE, ArgumentType.INT32);
CLASS_TO_ARGUMENTTYPE.put(Long.class, ArgumentType.INT64);
CLASS_TO_ARGUMENTTYPE.put(Long.TYPE, ArgumentType.INT64);
CLASS_TO_ARGUMENTTYPE.put(Double.class, ArgumentType.DOUBLE);
CLASS_TO_ARGUMENTTYPE.put(Double.TYPE, ArgumentType.DOUBLE);
if (AbstractConnection.FLOAT_SUPPORT) {
CLASS_TO_ARGUMENTTYPE.put(Float.class, ArgumentType.FLOAT);
CLASS_TO_ARGUMENTTYPE.put(Float.TYPE, ArgumentType.FLOAT);
} else {
CLASS_TO_ARGUMENTTYPE.put(Float.class, ArgumentType.DOUBLE);
CLASS_TO_ARGUMENTTYPE.put(Float.TYPE, ArgumentType.DOUBLE);
}
CLASS_TO_ARGUMENTTYPE.put(UInt16.class, ArgumentType.UINT16);
CLASS_TO_ARGUMENTTYPE.put(UInt32.class, ArgumentType.UINT32);
CLASS_TO_ARGUMENTTYPE.put(UInt64.class, ArgumentType.UINT64);
CLASS_TO_ARGUMENTTYPE.put(CharSequence.class, ArgumentType.STRING);
CLASS_TO_ARGUMENTTYPE.put(Variant.class, ArgumentType.VARIANT);
CLASS_TO_ARGUMENTTYPE.put(FileDescriptor.class, ArgumentType.FILEDESCRIPTOR);
CLASS_TO_ARGUMENTTYPE.put(DBusInterface.class, ArgumentType.OBJECT_PATH);
CLASS_TO_ARGUMENTTYPE.put(DBusPath.class, ArgumentType.OBJECT_PATH);
CLASS_TO_ARGUMENTTYPE.put(ObjectPath.class, ArgumentType.OBJECT_PATH);
}
private Marshalling() {
}
/**
* 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 _javaType The Java types.
* @return The DBus types.
*/
public static String getDBusType(Type[] _javaType) throws DBusException {
StringBuilder sb = new StringBuilder();
for (Type t : _javaType) {
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 _javaType The Java types.
* @return The DBus types
*
* @throws DBusTypeConversationRuntimeException when conversation fails
*
* @since 5.1.0 - 2024-05-19
*/
public static String convertJavaClassesToSignature(Class>... _javaType) throws DBusTypeConversationRuntimeException {
if (_javaType == null || _javaType.length == 0) {
throw new DBusTypeConversationRuntimeException("No types to convert given");
}
StringBuilder sig = new StringBuilder();
convertToSig(sig, 0, _javaType);
return sig.toString();
}
private static int convertToSig(StringBuilder _sig, int _idx, Class>... _javaType) {
for (int i = _idx; i < _javaType.length; i++) {
Class> clz = _javaType[i];
if (Collection.class.isAssignableFrom(clz)) {
_sig.append(ArgumentType.ARRAY_STRING);
} else if (Map.class.isAssignableFrom(clz)) {
_sig.append(ArgumentType.ARRAY_STRING).append(ArgumentType.DICT_ENTRY1_STRING);
i = convertToSig(_sig, i + 1, _javaType) - 1;
_sig.append(ArgumentType.DICT_ENTRY2_STRING);
return i;
} else if (CharSequence.class.isAssignableFrom(clz)) {
_sig.append(ArgumentType.STRING_STRING);
} else if (Struct.class.isAssignableFrom(clz)) {
_sig.append(ArgumentType.STRUCT1_STRING);
Class>[] structure = Arrays.stream(clz.getDeclaredFields())
.map(Field::getType)
.toArray(Class>[]::new);
convertToSig(_sig, 0, structure);
_sig.append(ArgumentType.STRUCT2_STRING);
return i;
} else if (Tuple.class.isAssignableFrom(clz)) {
continue; // simply ignore Tuple types
} else if (CLASS_TO_ARGUMENTTYPE.containsKey(clz)) {
char val = (char) CLASS_TO_ARGUMENTTYPE.get(clz).byteValue();
_sig.append(val);
} else {
throw new DBusTypeConversationRuntimeException("Unsupported class type " + clz);
}
}
return 0;
}
/**
* 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 _javaType 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 _javaType) throws DBusException {
String[] cached = TYPE_CACHE.get(_javaType);
if (null != cached) {
return cached;
}
cached = getDBusType(_javaType, false);
TYPE_CACHE.put(_javaType, 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 _dataType 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 _dataType, boolean _basic) throws DBusException {
return recursiveGetDBusType(new StringBuffer[INITIAL_BUFFER_SZ], _dataType, _basic, 0);
}
@SuppressWarnings("checkstyle:parameterassignment")
private static String[] recursiveGetDBusType(StringBuffer[] _out, Type _dataType, boolean _basic, int _level) throws DBusException {
if (_out.length <= _level) {
StringBuffer[] newout = new StringBuffer[_level + INITIAL_BUFFER_SZ];
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 && !(_dataType instanceof Class>)) {
throw new DBusException(_dataType + " is not a basic type");
}
if (_dataType instanceof WildcardType wildcardType && wildcardType.getUpperBounds().length > 0) {
return recursiveGetDBusType(_out, wildcardType.getUpperBounds()[0], _basic, _level);
} else if (_dataType instanceof TypeVariable) {
_out[_level].append((char) ArgumentType.VARIANT);
} else if (_dataType instanceof GenericArrayType gat) {
_out[_level].append((char) ArgumentType.ARRAY);
String[] s = recursiveGetDBusType(_out, gat.getGenericComponentType(), false, _level + 1);
if (s.length != 1) {
throw new DBusException(ERROR_MULTI_VALUED_ARRAY);
}
_out[_level].append(s[0]);
} else if (_dataType instanceof Class> && DBusSerializable.class.isAssignableFrom((Class>) _dataType)
|| _dataType instanceof ParameterizedType pt
&& DBusSerializable.class.isAssignableFrom((Class>) pt.getRawType())) {
// it's a custom serializable type
Type[] newtypes = null;
if (_dataType instanceof Class> clz) {
for (Method m : clz.getDeclaredMethods()) {
if (m.getName().equals(MTH_NAME_DESERIALIZE)) {
newtypes = m.getGenericParameterTypes();
}
}
} else {
for (Method m : ((Class>) ((ParameterizedType) _dataType).getRawType()).getDeclaredMethods()) {
if (m.getName().equals(MTH_NAME_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(_out, 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 (_dataType instanceof ParameterizedType p) {
if (p.getRawType().equals(Map.class)) {
_out[_level].append(ArgumentType.ARRAY_STRING)
.append(ArgumentType.DICT_ENTRY1_STRING);
Type[] t = p.getActualTypeArguments();
try {
String[] s = recursiveGetDBusType(_out, t[0], true, _level + 1);
if (s.length != 1) {
throw new DBusException(ERROR_MULTI_VALUED_ARRAY);
}
_out[_level].append(s[0]);
s = recursiveGetDBusType(_out, t[1], false, _level + 1);
if (s.length != 1) {
throw new DBusException(ERROR_MULTI_VALUED_ARRAY);
}
_out[_level].append(s[0]);
} catch (ArrayIndexOutOfBoundsException _ex) {
LOGGER.debug("", _ex);
throw new DBusException("Map must have 2 parameters");
}
_out[_level].append(ArgumentType.DICT_ENTRY2_STRING);
} else if (List.class.isAssignableFrom((Class>) p.getRawType())) {
for (Type t : p.getActualTypeArguments()) {
if (Type.class.equals(t)) {
_out[_level].append((char) ArgumentType.SIGNATURE);
} else {
String[] s = recursiveGetDBusType(_out, t, false, _level + 1);
if (s.length != 1) {
throw new DBusException(ERROR_MULTI_VALUED_ARRAY);
}
_out[_level].append((char) ArgumentType.ARRAY);
_out[_level].append(s[0]);
}
}
} else if (p.getRawType().equals(Variant.class)) {
_out[_level].append((char) ArgumentType.VARIANT);
} else if (DBusInterface.class.isAssignableFrom((Class>) p.getRawType())) {
_out[_level].append((char) ArgumentType.OBJECT_PATH);
} else if (Struct.class.isAssignableFrom((Class>) p.getRawType())) {
_out[_level].append((char) ArgumentType.STRUCT1);
} else if (Tuple.class.isAssignableFrom((Class>) p.getRawType())) {
Type[] ts = p.getActualTypeArguments();
List vs = new ArrayList<>();
for (Type t : ts) {
Collections.addAll(vs, recursiveGetDBusType(_out, t, false, _level + 1));
}
return vs.toArray(EMPTY_STRING_ARRAY);
} else {
throw new DBusException("Exporting non-exportable parameterized type " + _dataType);
}
} else if (_dataType instanceof Class> dataTypeClazz) {
if (dataTypeClazz.isArray()) {
if (Type.class.equals(((Class>) _dataType).getComponentType())) {
_out[_level].append((char) ArgumentType.SIGNATURE);
} else {
_out[_level].append((char) ArgumentType.ARRAY);
String[] s = recursiveGetDBusType(_out, ((Class>) _dataType).getComponentType(), false, _level + 1);
if (s.length != 1) {
throw new DBusException(ERROR_MULTI_VALUED_ARRAY);
}
_out[_level].append(s[0]);
}
} else if (Struct.class.isAssignableFrom((Class>) _dataType)) {
_out[_level].append((char) ArgumentType.STRUCT1);
Type[] ts = Container.getTypeCache(_dataType);
if (null == ts) {
Field[] fs = ((Class>) _dataType).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(_dataType, ts);
}
for (Type t : ts) {
if (t != null) {
for (String s : recursiveGetDBusType(_out, t, false, _level + 1)) {
_out[_level].append(s);
}
}
}
_out[_level].append(ArgumentType.STRUCT2_STRING);
} else if (Enum.class.isAssignableFrom(dataTypeClazz)) {
_out[_level].append((char) ArgumentType.STRING);
} else {
boolean found = false;
for (Entry, Byte> entry : CLASS_TO_ARGUMENTTYPE.entrySet()) {
if (entry.getKey().isAssignableFrom(dataTypeClazz)) {
_out[_level].append((char) entry.getValue().byteValue());
found = true;
break;
}
}
if (!found) {
throw new DBusException("Exporting non-exportable type: " + _dataType);
}
}
}
LOGGER.trace("Converted Java type: {} to D-Bus Type: {}", _dataType, _out[_level]);
return new String[] {
_out[_level].toString()
};
}
/**
* Converts a dbus type string into Java Type objects,
* @param _dbusType The DBus type or types.
* @param _resultValue List to return the types in.
* @param _limit Maximum number of types to parse (-1 == nolimit).
* @return number of characters parsed from the type string.
* @throws DBusException on error
*/
public static int getJavaType(String _dbusType, List _resultValue, int _limit) throws DBusException {
if (null == _dbusType || _dbusType.isEmpty() || 0 == _limit) {
return 0;
}
try {
int idx = 0;
for (; idx < _dbusType.length() && (-1 == _limit || _limit > _resultValue.size()); idx++) {
switch (_dbusType.charAt(idx)) {
case ArgumentType.STRUCT1:
int structIdx = idx + 1;
for (int structLen = 1; structLen > 0; structIdx++) {
if (ArgumentType.STRUCT2 == _dbusType.charAt(structIdx)) {
structLen--;
} else if (ArgumentType.STRUCT1 == _dbusType.charAt(structIdx)) {
structLen++;
}
}
List contained = new ArrayList<>();
getJavaType(_dbusType.substring(idx + 1, structIdx - 1), contained, -1);
_resultValue.add(new DBusStructType(contained.toArray(EMPTY_TYPE_ARRAY)));
idx = structIdx - 1; //-1 because j already points to the next signature char
break;
case ArgumentType.ARRAY:
if (ArgumentType.DICT_ENTRY1 == _dbusType.charAt(idx + 1)) {
contained = new ArrayList<>();
int javaType = getJavaType(_dbusType.substring(idx + 2), contained, 2);
_resultValue.add(new DBusMapType(contained.get(0), contained.get(1)));
idx += javaType + 2;
} else {
contained = new ArrayList<>();
int javaType = getJavaType(_dbusType.substring(idx + 1), contained, 1);
_resultValue.add(new DBusListType(contained.get(0)));
idx += javaType;
}
break;
case ArgumentType.VARIANT:
_resultValue.add(Variant.class);
break;
case ArgumentType.BOOLEAN:
_resultValue.add(Boolean.class);
break;
case ArgumentType.INT16:
_resultValue.add(Short.class);
break;
case ArgumentType.BYTE:
_resultValue.add(Byte.class);
break;
case ArgumentType.OBJECT_PATH:
_resultValue.add(DBusPath.class);
break;
case ArgumentType.UINT16:
_resultValue.add(UInt16.class);
break;
case ArgumentType.INT32:
_resultValue.add(Integer.class);
break;
case ArgumentType.UINT32:
_resultValue.add(UInt32.class);
break;
case ArgumentType.INT64:
_resultValue.add(Long.class);
break;
case ArgumentType.UINT64:
_resultValue.add(UInt64.class);
break;
case ArgumentType.DOUBLE:
_resultValue.add(Double.class);
break;
case ArgumentType.FLOAT:
_resultValue.add(Float.class);
break;
case ArgumentType.STRING:
_resultValue.add(CharSequence.class);
break;
case ArgumentType.FILEDESCRIPTOR:
_resultValue.add(FileDescriptor.class);
break;
case ArgumentType.SIGNATURE:
_resultValue.add(Type[].class);
break;
case ArgumentType.DICT_ENTRY1:
contained = new ArrayList<>();
int javaType = getJavaType(_dbusType.substring(idx + 1), contained, 2);
_resultValue.add(new DBusMapType(contained.get(0), contained.get(1)));
idx += javaType + 1;
break;
default:
throw new DBusException(String.format("Failed to parse DBus type signature: %s (%s).", _dbusType, _dbusType.charAt(idx)));
}
}
return idx;
} catch (IndexOutOfBoundsException _ex) {
LOGGER.debug("Failed to parse DBus type signature.", _ex);
throw new DBusException("Failed to parse DBus type signature: " + _dbusType);
}
}
/**
* Recursively converts types for serialization onto DBus.
*
* When _customSignature is not empty or null, it will be used to wrap the given parameters to a {@link Variant}
* of the type defined in the _customSignature array.
* It is required that every {@link Variant} passed has a signature definition in _customSignature.
* E.g. 3 Objects are given in _parameters: String, Variant, Variant.
* Then it is expected that _customSignature (if used) contains 2 entries one for each {@link Variant}.
*
* If the _customSignature is smaller than the count of {@link Variant}s in _parameters, all remaining {@link Variant}s
* are created without a explicit signature (Variant constructor will try to determine type automatically).
* If more entries are given then {@link Variant}s found in _parameters, the additional signatures are ignored.
*
* @param _parameters The parameters to convert.
* @param _types The (possibly generic) types of the parameters.
* @param _customSignatures custom signatures used for variants found in _types, each found variant must have one matching custom signature
* @param _conn the connection
* @return The converted parameters.
* @throws DBusException Thrown if there is an error in converting the objects.
*/
public static Object[] convertParameters(Object[] _parameters, Type[] _types, String[] _customSignatures, AbstractConnectionBase _conn) throws DBusException {
if (_parameters == null) {
return null;
}
Object[] parameters = _parameters;
Type[] types = _types;
int lastCustomSig = 0;
for (int i = 0; i < parameters.length; i++) {
if (null == parameters[i]) {
continue;
}
LOGGER.trace("Converting {} from '{}' to {}", i, parameters[i], types[i]);
if (parameters[i] instanceof DBusSerializable ds) {
for (Method m : parameters[i].getClass().getDeclaredMethods()) {
if (m.getName().equals(MTH_NAME_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 = ds.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 tup) {
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 = tup.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;
LoggingHelper.logIf(LOGGER.isTraceEnabled(),
() -> LOGGER.trace("New params: {}, new types: {}", Arrays.deepToString(exparams), Arrays.deepToString(expand)));
i--;
} else if (types[i] instanceof TypeVariable && !(parameters[i] instanceof Variant)) {
// its an unwrapped variant, wrap it
if (_customSignatures != null && _customSignatures.length > 0 && _customSignatures.length > lastCustomSig) {
parameters[i] = new Variant<>(parameters[i], _customSignatures[lastCustomSig]);
lastCustomSig++;
} else {
parameters[i] = new Variant<>(parameters[i]);
}
} else if (parameters[i] instanceof DBusInterface di) {
parameters[i] = _conn.getExportedObject(di);
}
}
return parameters;
}
/**
* Recursively converts types for serialization onto DBus.
*
* @param _parameters The parameters to convert.
* @param _types The (possibly generic) types of the parameters.
* @param _conn the connection
* @return The converted parameters.
* @throws DBusException Thrown if there is an error in converting the objects.
*/
public static Object[] convertParameters(Object[] _parameters, Type[] _types, AbstractConnectionBase _conn) throws DBusException {
return convertParameters(_parameters, _types, null, _conn);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
static Object deSerializeParameter(Object _parameter, Type _type, AbstractConnectionBase _conn) throws Exception {
LOGGER.trace("Deserializing from {} to {}", _parameter.getClass(), _type);
Object parameter = _parameter;
// its a wrapped variant, unwrap it
if (_type instanceof TypeVariable && parameter instanceof Variant> variant) {
parameter = variant.getValue();
LOGGER.trace("Type is variant, unwrapping to {}", parameter);
}
// Turn a signature into a Type[]
if (_type instanceof Class && ((Class>) _type).isArray() && ((Class>) _type).getComponentType().equals(Type.class) && parameter instanceof String) {
List rv = new ArrayList<>();
getJavaType((String) parameter, rv, -1);
parameter = rv.toArray(EMPTY_TYPE_ARRAY);
}
// its an object path, get/create the proxy
if (parameter instanceof ObjectPath op) {
LOGGER.trace("Parameter is ObjectPath");
if (_type instanceof Class && DBusInterface.class.isAssignableFrom((Class>) _type)) {
parameter = _conn.getExportedObject(op.getSource(), op.getPath(), (Class) _type);
} else {
parameter = new DBusPath(op.getPath());
}
}
if (parameter instanceof DBusPath op) {
LOGGER.trace("Parameter is DBusPath");
if (_type instanceof Class && DBusInterface.class.isAssignableFrom((Class>) _type)) {
parameter = _conn.getExportedObject(op.getSource(), op.getPath(), (Class) _type);
} else {
parameter = new DBusPath(op.getPath());
}
}
// its an enum, parse either as the string name or the ordinal
if (parameter instanceof String str && _type instanceof Class && Enum.class.isAssignableFrom((Class>) _type)) {
LOGGER.trace("Type seems to be an enum");
parameter = Enum.valueOf((Class) _type, str);
}
// it should be a struct. create it
if (parameter instanceof Object[] objArr && _type instanceof Class && Struct.class.isAssignableFrom((Class>) _type)) {
LOGGER.trace("Creating Struct {} from {}", _type, parameter);
Type[] ts = Container.getTypeCache(_type);
if (ts == null) {
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(objArr, ts, _conn);
for (Constructor> con : ((Class>) _type).getDeclaredConstructors()) {
try {
parameter = con.newInstance(objArr);
break;
} catch (IllegalArgumentException _exIa) {
LOGGER.trace("Could not create new instance", _exIa);
}
}
}
// recurse over arrays
if (parameter instanceof Object[] oa) {
LOGGER.trace("Parameter is object array");
Type[] ts = new Type[oa.length];
Arrays.fill(ts, parameter.getClass().getComponentType());
parameter = deSerializeParameters(oa, ts, _conn);
}
if (parameter instanceof List) {
LOGGER.trace("Parameter is List");
Type type2;
if (_type instanceof ParameterizedType pt) {
type2 = pt.getActualTypeArguments()[0];
} else if (_type instanceof GenericArrayType gat) {
type2 = gat.getGenericComponentType();
} else if (_type instanceof Class> clz && ((Class>) _type).isArray()) {
type2 = clz.getComponentType();
} else {
type2 = null;
}
LOGGER.trace("Type is: {}", type2);
if (null != type2) {
parameter = deSerializeParameters((List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy