From 89a0f776d4938ac78d4180e328342ede68c47482 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Wed, 8 Sep 2021 13:52:28 +0200 Subject: [PATCH] Add possibility for Tuples as return types to dbus method calls In dbus it is possible for a method to have multiple return types. To map this into the java world, the dbus-java library wraps the return types into a class, that contains all desired values as fields. This class extends the Tuple class and is normally generated by the InterfaceCodeGenerator. There was a piece missing in the library, that could deal with such Tuples as a return type to a dbus method call. This commit adds the missing piece and a little test case. --- .../org/freedesktop/dbus/Marshalling.java | 15 ++++++++ .../dbus/test/MarshallingTest.java | 35 +++++++++++++------ .../dbus/test/helper/structs/MarkTuple.java | 33 +++++++++++++++++ 3 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 dbus-java/src/test/java/org/freedesktop/dbus/test/helper/structs/MarkTuple.java diff --git a/dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java b/dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java index 78431a39..cd3437db 100644 --- a/dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java +++ b/dbus-java/src/main/java/org/freedesktop/dbus/Marshalling.java @@ -628,6 +628,21 @@ public static Object[] deSerializeParameters(Object[] _parameters, Type[] _types _types = ((ParameterizedType) _types[0]).getActualTypeArguments(); } + if (_types.length == 1 && Tuple.class.isAssignableFrom((Class) _types[0])) { + String typeName = _types[0].getTypeName(); + Constructor[] constructors = Class.forName(typeName).getDeclaredConstructors(); + if (constructors.length != 1) { + throw new DBusException("Error deserializing message: We had a Tuple type but wrong number of constructors for this Tuple. There should be exactly one."); + } + + if (constructors[0].getParameterCount() != _parameters.length) { + throw new DBusException("Error deserializing message: We had a Tuple type but it had wrong number of constructor arguments. The number of constructor arguments should match the number of parameters to deserialize."); + } + + Object o = constructors[0].newInstance(_parameters); + return new Object[] {o}; + } + 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) { diff --git a/dbus-java/src/test/java/org/freedesktop/dbus/test/MarshallingTest.java b/dbus-java/src/test/java/org/freedesktop/dbus/test/MarshallingTest.java index 485b91c4..0d244da8 100644 --- a/dbus-java/src/test/java/org/freedesktop/dbus/test/MarshallingTest.java +++ b/dbus-java/src/test/java/org/freedesktop/dbus/test/MarshallingTest.java @@ -1,22 +1,15 @@ package org.freedesktop.dbus.test; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.File; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.GenericDeclaration; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; +import java.lang.reflect.*; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.freedesktop.dbus.DBusPath; -import org.freedesktop.dbus.Marshalling; -import org.freedesktop.dbus.ObjectPath; -import org.freedesktop.dbus.Struct; +import jnr.ffi.annotations.In; +import org.freedesktop.dbus.*; import org.freedesktop.dbus.annotations.DBusInterfaceName; import org.freedesktop.dbus.annotations.Position; import org.freedesktop.dbus.exceptions.DBusException; @@ -24,11 +17,14 @@ import org.freedesktop.dbus.messages.DBusSignal; import org.freedesktop.dbus.messages.Message; import org.freedesktop.dbus.messages.MessageFactory; +import org.freedesktop.dbus.test.helper.structs.MarkTuple; import org.freedesktop.dbus.types.DBusListType; import org.freedesktop.dbus.types.Variant; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + public class MarshallingTest { @Test @@ -86,7 +82,20 @@ public void testMarshalling() throws Exception { assertTrue(params[1] instanceof List, "Second param is not a List"); } - + + @Test + public void testDeserializeParametersWithTuple() throws Exception { + Object[] ob = { new String("rootfs.1"), new String("marked slot rootfs.1 as good")}; + Method m = Installer.class.getDeclaredMethod("Mark", String.class, String.class); + Type[] ts = new Type[] { m.getGenericReturnType() }; + + Object[] params = Marshalling.deSerializeParameters(ob, ts, null); + + assertTrue(params[0] instanceof MarkTuple, "First param is not a MarkTuple"); + MarkTuple mt = (MarkTuple) params[0]; + assertEquals(mt.getSlotName(), "rootfs.1", "Slot name does not match after deSerialization"); + assertEquals(mt.getMessage(), "marked slot rootfs.1 as good", "Message does not match after deSerialization"); + } /* ****************************************** @@ -158,4 +167,8 @@ void setProperties(Map> _properties) { } + + public interface Installer extends DBusInterface { + public MarkTuple Mark(String state, String slotIdentifier); + } } diff --git a/dbus-java/src/test/java/org/freedesktop/dbus/test/helper/structs/MarkTuple.java b/dbus-java/src/test/java/org/freedesktop/dbus/test/helper/structs/MarkTuple.java new file mode 100644 index 00000000..2ed1bcbd --- /dev/null +++ b/dbus-java/src/test/java/org/freedesktop/dbus/test/helper/structs/MarkTuple.java @@ -0,0 +1,33 @@ +package org.freedesktop.dbus.test.helper.structs; + +import org.freedesktop.dbus.Tuple; +import org.freedesktop.dbus.annotations.Position; + +public class MarkTuple extends Tuple { + @Position(0) + private String slotName; + @Position(1) + private String message; + + public MarkTuple(String slotName, String message) { + this.slotName = slotName; + this.message = message; + } + + public void setSlotName(String arg) { + slotName = arg; + } + + public String getSlotName() { + return slotName; + } + public void setMessage(String arg) { + message = arg; + } + + public String getMessage() { + return message; + } + + +}