Skip to content

Commit ce368ea

Browse files
authored
Merge pull request hypfvieh#43 from Technolution/fork_pull_request
Support for empty collections + some fixes
2 parents f33fd8a + 3b67f12 commit ce368ea

25 files changed

Lines changed: 1380 additions & 32 deletions

dbus-java/src/main/java/org/freedesktop/dbus/connections/impl/DBusConnection.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.io.IOException;
1717
import java.lang.reflect.Proxy;
1818
import java.util.ArrayList;
19+
import java.util.Arrays;
1920
import java.util.Iterator;
2021
import java.util.List;
2122
import java.util.Map.Entry;
@@ -63,10 +64,12 @@
6364
* </p>
6465
*/
6566
public final class DBusConnection extends AbstractConnection {
66-
private final Logger logger = LoggerFactory.getLogger(getClass());
67+
68+
private final Logger logger = LoggerFactory.getLogger(getClass());
6769

6870
public static final String DEFAULT_SYSTEM_BUS_ADDRESS =
6971
"unix:path=/var/run/dbus/system_bus_socket";
72+
private static final String DBUS_MACHINE_ID_SYS_VAR = "DBUS_MACHINE_ID_LOCATION";
7073

7174
private List<String> busnames;
7275

@@ -256,22 +259,13 @@ private AtomicInteger getConcurrentConnections() {
256259

257260
/**
258261
* Extracts the machine-id usually found in /var/lib/dbus/machine-id.
262+
* Use system variable DBUS_MACHINE_ID_LOCATION to use other location
259263
*
260264
* @return machine-id string, never null
261265
* @throws DBusException if machine-id could not be found
262266
*/
263267
public static String getDbusMachineId() throws DBusException {
264-
File uuidfile = new File("/var/lib/dbus/machine-id");
265-
if (!uuidfile.exists()) {
266-
uuidfile = new File("/usr/local/var/lib/dbus/machine-id");
267-
}
268-
if (!uuidfile.exists()) {
269-
uuidfile = new File("/etc/machine-id");
270-
}
271-
if (!uuidfile.exists()) {
272-
throw new DBusException("Cannot Resolve Session Bus Address");
273-
}
274-
268+
File uuidfile = determineMachineIdFile();
275269
String uuid = FileIoUtil.readFileToString(uuidfile);
276270
if (StringUtil.isEmpty(uuid)) {
277271
throw new DBusException("Cannot Resolve Session Bus Address: MachineId file is empty.");
@@ -280,6 +274,17 @@ public static String getDbusMachineId() throws DBusException {
280274
return uuid;
281275
}
282276

277+
private static File determineMachineIdFile() throws DBusException {
278+
List<String> locationPriorityList = Arrays.asList(System.getenv(DBUS_MACHINE_ID_SYS_VAR),
279+
"/var/lib/dbus/machine-id", "/usr/local/var/lib/dbus/machine-id", "/etc/machine-id");
280+
return locationPriorityList.stream()
281+
.filter(s -> s != null)
282+
.map(s -> new File(s))
283+
.filter(f -> f.exists())
284+
.findFirst()
285+
.orElseThrow(() -> new DBusException("Cannot Resolve Session Bus Address: MachineId file can not be found"));
286+
}
287+
283288
private DBusConnection(String _address, boolean _shared, boolean _registerSelf, String _machineId) throws DBusException {
284289
super(_address);
285290
busnames = new ArrayList<>();

dbus-java/src/main/java/org/freedesktop/dbus/connections/transports/TcpTransport.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ void connect() throws IOException {
3838
socket = new Socket();
3939
socket.connect(new InetSocketAddress(getAddress().getHost(), getAddress().getPort()));
4040
}
41-
41+
42+
setInputReader(socket.getInputStream());
43+
setOutputWriter(socket.getOutputStream());
4244
getLogger().trace("Setting timeout to {} on Socket", getTimeout());
4345
socket.setSoTimeout(getTimeout());
4446

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
D-Bus Java Implementation
3+
Copyright (c) 2019 Technolution BV
4+
5+
This program is free software; you can redistribute it and/or modify it
6+
under the terms of either the GNU Lesser General Public License Version 2 or the
7+
Academic Free Licence Version 2.1.
8+
9+
Full licence texts are included in the LICENSE file with this program.
10+
*/
11+
12+
package org.freedesktop.dbus.messages;
13+
14+
import java.util.Arrays;
15+
16+
final class EmptyCollectionHelper {
17+
18+
/**
19+
* This function determine the new offset in signature for empty Dictionary/Map collections.
20+
* Normally the element inside a collection determines the new offset,
21+
* however in case of empty collections there is no element to determine the sub signature of the list
22+
* so this function determines which part of the signature to skip
23+
* @param sigb the total signature
24+
* @param currentOffset the current offset within the signature
25+
* @return the index of the last element of the collection (subtype)
26+
*/
27+
static int determineSignatureOffsetDict(byte[] sigb, int currentOffset) {
28+
return determineEndOfBracketStructure(sigb, currentOffset, '{' , '}');
29+
}
30+
31+
/**
32+
* This function determine the new offset in signature for empty Array/List collections.
33+
* Normally the element inside a collection determines the new offset,
34+
* however in case of empty collections there is no element to determine the sub signature of the list
35+
* so this function determines which part of the signature to skip
36+
* @param sigb the total signature
37+
* @param currentOffset the current offset within the signature
38+
* @return the index of the last element of the collection (subtype)
39+
*/
40+
static int determineSignatureOffsetArray(byte[] sigb, int currentOffset) {
41+
String sigSubString = determineSubSignature(sigb, currentOffset);
42+
43+
// End of string so can't have any more offset
44+
if (sigSubString.isEmpty()) {
45+
return currentOffset;
46+
}
47+
48+
ECollectionSubType newtype = determineCollectionSubType((char)sigb[currentOffset]);
49+
switch (newtype) {
50+
case ARRAY:
51+
// array in array so look at the next type
52+
return determineSignatureOffsetArray(sigb, currentOffset + 1);
53+
case DICT:
54+
return determineSignatureOffsetDict(sigb, currentOffset);
55+
case STRUCT:
56+
return determineSignatureOffsetStruct(sigb, currentOffset);
57+
case PRIMITIVE:
58+
//primitive is always one element so no need to skip more
59+
return currentOffset;
60+
default:
61+
break;
62+
63+
}
64+
throw new IllegalStateException("Unable to parse signature for empty collection");
65+
}
66+
67+
private static int determineSignatureOffsetStruct(byte[] sigb, int currentOffset) {
68+
return determineEndOfBracketStructure(sigb, currentOffset, '(' , ')');
69+
}
70+
71+
/**
72+
* This is a generic function to determine the end of a structure that has opening and closing characters.
73+
* Currently used for Struct () and Dict {}
74+
*
75+
*/
76+
private static int determineEndOfBracketStructure(byte[] sigb, int currentOffset, char openChar, char closeChar) {
77+
String sigSubString = determineSubSignature(sigb, currentOffset);
78+
79+
// End of string so can't have any more offset
80+
if (sigSubString.isEmpty()) {
81+
return currentOffset;
82+
}
83+
int i = 0;
84+
int depth = 0;
85+
86+
for(char chr : sigSubString.toCharArray()) {
87+
//book keeping of depth of nested structures to solve opening closing bracket problem
88+
if (chr == openChar) {
89+
depth ++;
90+
} else if (chr == closeChar) {
91+
depth --;
92+
}
93+
if (depth == 0) {
94+
return currentOffset + i;
95+
}
96+
i++;
97+
}
98+
throw new IllegalStateException("Unable to parse signature for empty collection");
99+
}
100+
101+
private static String determineSubSignature(byte[] sigb, int currentOffset) {
102+
byte[] restSigbytes = Arrays.copyOfRange(sigb, currentOffset, sigb.length);
103+
return new String(restSigbytes);
104+
}
105+
106+
/**
107+
* The starting type determines of a collection determines when it ends
108+
* @param sig the signature letter of the type
109+
*/
110+
private static ECollectionSubType determineCollectionSubType(char sig) {
111+
switch (sig) {
112+
case '(':
113+
return ECollectionSubType.STRUCT;
114+
case '{':
115+
return ECollectionSubType.DICT;
116+
case 'a':
117+
return ECollectionSubType.ARRAY;
118+
default:
119+
// of course there can be other types but those shouldn't be allowed in this part of the signature
120+
return ECollectionSubType.PRIMITIVE;
121+
}
122+
}
123+
124+
/**
125+
* Internal Enumeration used to group the types of element
126+
*/
127+
enum ECollectionSubType {
128+
STRUCT,
129+
DICT,
130+
ARRAY,
131+
PRIMITIVE
132+
}
133+
}

dbus-java/src/main/java/org/freedesktop/dbus/messages/Message.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -661,21 +661,19 @@ private int appendone(byte[] sigb, int sigofs, Object data) throws DBusException
661661
for (Object o : contents) {
662662
diff = appendone(sigb, i, o);
663663
}
664+
if (contents.length == 0) {
665+
diff = EmptyCollectionHelper.determineSignatureOffsetArray(sigb, diff);
666+
}
664667
i = diff;
665668
} else if (data instanceof Map) {
666669
int diff = i;
667-
ensureBuffers(((Map<?, ?>) data).size() * 6);
668-
for (Map.Entry<Object, Object> o : ((Map<Object, Object>) data).entrySet()) {
670+
Map<Object, Object> map = (Map<Object, Object>) data;
671+
ensureBuffers(map.size() * 6);
672+
for (Map.Entry<Object, Object> o : map.entrySet()) {
669673
diff = appendone(sigb, i, o);
670674
}
671-
if (i == diff) {
672-
// advance the type parser even on 0-size arrays.
673-
List<Type> temp = new ArrayList<>();
674-
byte[] temp2 = new byte[sigb.length - diff];
675-
System.arraycopy(sigb, diff, temp2, 0, temp2.length);
676-
String temp3 = new String(temp2);
677-
int temp4 = Marshalling.getJavaType(temp3, temp, 1);
678-
diff += temp4;
675+
if (map.size() == 0) {
676+
diff = EmptyCollectionHelper.determineSignatureOffsetDict(sigb, diff);
679677
}
680678
i = diff;
681679
} else {
@@ -685,6 +683,9 @@ private int appendone(byte[] sigb, int sigofs, Object data) throws DBusException
685683
for (Object o : contents) {
686684
diff = appendone(sigb, i, o);
687685
}
686+
if (contents.length == 0) {
687+
diff = EmptyCollectionHelper.determineSignatureOffsetArray(sigb, diff);
688+
}
688689
i = diff;
689690
}
690691
logger.trace("start: {} end: {} length: {}", c, bytecounter, (bytecounter - c));

dbus-java/src/test/java/org/freedesktop/dbus/test/TestAll.java

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,18 @@
6868
import org.freedesktop.dbus.test.helper.signals.handler.PathSignalHandler;
6969
import org.freedesktop.dbus.test.helper.signals.handler.RenamedSignalHandler;
7070
import org.freedesktop.dbus.test.helper.signals.handler.SignalHandler;
71+
import org.freedesktop.dbus.test.helper.structs.IntStruct;
7172
import org.freedesktop.dbus.test.helper.structs.SampleStruct;
7273
import org.freedesktop.dbus.test.helper.structs.SampleStruct2;
7374
import org.freedesktop.dbus.test.helper.structs.SampleStruct3;
75+
import org.freedesktop.dbus.test.helper.structs.SampleStruct4;
7476
import org.freedesktop.dbus.test.helper.structs.SampleTuple;
7577
import org.freedesktop.dbus.types.UInt16;
7678
import org.freedesktop.dbus.types.UInt32;
7779
import org.freedesktop.dbus.types.UInt64;
7880
import org.freedesktop.dbus.types.Variant;
79-
import org.junit.jupiter.api.AfterAll;
80-
import org.junit.jupiter.api.BeforeAll;
81+
import org.junit.jupiter.api.AfterEach;
82+
import org.junit.jupiter.api.BeforeEach;
8183
import org.junit.jupiter.api.Test;
8284

8385
import com.github.hypfvieh.util.TimeMeasure;
@@ -91,13 +93,13 @@ public class TestAll {
9193
public static final String TEST_OBJECT_PATH = "/TestAll";
9294

9395
// CHECKSTYLE:OFF
94-
private static DBusConnection serverconn = null;
95-
private static DBusConnection clientconn = null;
96-
private static SampleClass tclass;
96+
private DBusConnection serverconn = null;
97+
private DBusConnection clientconn = null;
98+
private SampleClass tclass;
9799
// CHECKSTYLE:ON
98100

99-
@BeforeAll
100-
public static void beforeClass() throws DBusException {
101+
@BeforeEach
102+
public void setUp() throws DBusException {
101103
serverconn = DBusConnection.getConnection(DBusBusType.SESSION);
102104
clientconn = DBusConnection.getConnection(DBusBusType.SESSION);
103105
serverconn.setWeakReferences(true);
@@ -111,8 +113,8 @@ public static void beforeClass() throws DBusException {
111113
serverconn.addFallback("/FallbackTest", tclass);
112114
}
113115

114-
@AfterAll
115-
public static void afterClass() {
116+
@AfterEach
117+
public void tearDown() {
116118
System.out.println("Checking for outstanding errors");
117119
DBusExecutionException dbee = serverconn.getError();
118120
if (null != dbee) {
@@ -379,6 +381,24 @@ public void testStruct() throws DBusException {
379381
}
380382
}
381383

384+
@Test
385+
public void testListOfStruct() throws DBusException {
386+
SampleRemoteInterface tri = (SampleRemoteInterface) clientconn.getPeerRemoteObject("foo.bar.Test", TEST_OBJECT_PATH);
387+
388+
IntStruct elem1 = new IntStruct(3, 7);
389+
IntStruct elem2 = new IntStruct(9, 14);
390+
List<IntStruct> list = Arrays.asList(elem1, elem2);
391+
SampleStruct4 param = new SampleStruct4(list);
392+
int[][] out = tri.testListstruct(param);
393+
if (out.length != 2) {
394+
fail("teststructstruct returned the wrong thing: " + Arrays.deepToString(out));
395+
}
396+
assertEquals(elem1.getValue1(), out[0][0]);
397+
assertEquals(elem1.getValue2(), out[0][1]);
398+
assertEquals(elem2.getValue1(), out[1][0]);
399+
assertEquals(elem2.getValue2(), out[1][1]);
400+
}
401+
382402
public void testFrob() throws DBusException {
383403
SampleRemoteInterface tri = (SampleRemoteInterface) clientconn.getPeerRemoteObject("foo.bar.Test", TEST_OBJECT_PATH);
384404
System.out.println("frobnicating");
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
D-Bus Java Implementation
3+
Copyright (c) 2019 Technolution BV
4+
5+
This program is free software; you can redistribute it and/or modify it
6+
under the terms of either the GNU Lesser General Public License Version 2 or the
7+
Academic Free Licence Version 2.1.
8+
9+
Full licence texts are included in the LICENSE file with this program.
10+
*/
11+
12+
package org.freedesktop.dbus.test.collections.empty;
13+
14+
import org.freedesktop.dbus.interfaces.DBusInterface;
15+
import org.freedesktop.dbus.test.collections.empty.structs.ArrayStructIntStruct;
16+
import org.freedesktop.dbus.test.collections.empty.structs.ArrayStructPrimitive;
17+
import org.freedesktop.dbus.test.collections.empty.structs.DeepArrayStruct;
18+
import org.freedesktop.dbus.test.collections.empty.structs.DeepListStruct;
19+
import org.freedesktop.dbus.test.collections.empty.structs.DeepMapStruct;
20+
import org.freedesktop.dbus.test.collections.empty.structs.ListMapStruct;
21+
import org.freedesktop.dbus.test.collections.empty.structs.ListStructPrimitive;
22+
import org.freedesktop.dbus.test.collections.empty.structs.ListStructStruct;
23+
import org.freedesktop.dbus.test.collections.empty.structs.MapArrayStruct;
24+
import org.freedesktop.dbus.test.collections.empty.structs.MapStructIntStruct;
25+
import org.freedesktop.dbus.test.collections.empty.structs.MapStructPrimitive;
26+
27+
/**
28+
* A sample remote interface which implements same function for all of the structs
29+
*/
30+
public interface ISampleCollectionInterface extends DBusInterface {
31+
32+
String testListPrimitive(ListStructPrimitive param);
33+
34+
String testListIntStruct(ListStructStruct param);
35+
36+
String testDeepList(DeepListStruct param);
37+
38+
String testArrayPrimitive(ArrayStructPrimitive param);
39+
40+
String testArrayIntStruct(ArrayStructIntStruct param);
41+
42+
String testDeepArray(DeepArrayStruct param);
43+
44+
String testMapPrimitive(MapStructPrimitive param);
45+
46+
String testMapIntStruct(MapStructIntStruct param);
47+
48+
String testDeepMap(DeepMapStruct param);
49+
50+
String testMixedListMap(ListMapStruct param);
51+
52+
String testMixedMapArray(MapArrayStruct param);
53+
54+
}

0 commit comments

Comments
 (0)