) o[0];
380 | }
381 | }
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/KWallet.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet;
2 |
3 | import org.freedesktop.dbus.annotations.DBusInterfaceName;
4 | import org.freedesktop.dbus.annotations.MethodNoReply;
5 | import org.freedesktop.dbus.exceptions.DBusException;
6 | import org.freedesktop.dbus.interfaces.DBusInterface;
7 | import org.freedesktop.dbus.messages.DBusSignal;
8 |
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | @DBusInterfaceName("org.kde.KWallet")
13 | public interface KWallet extends DBusInterface {
14 |
15 | public static class walletListDirty extends DBusSignal {
16 | /**
17 | * A wallet was modified, but not yet saved to disc.
18 | *
19 | * @param path The path to the object this is emitted from.
20 | * @throws DBusException Could not communicate properly with the D-Bus.
21 | */
22 | public walletListDirty(String path) throws DBusException {
23 | super(path);
24 | }
25 | }
26 |
27 | public static class walletCreated extends DBusSignal {
28 | public final String wallet;
29 |
30 | /**
31 | * A new wallet was created.
32 | *
33 | * @param path The path to the object this is emitted from.
34 | * @param wallet The wallet that has been created.
35 | * @throws DBusException Could not communicate properly with the D-Bus.
36 | */
37 | public walletCreated(String path, String wallet) throws DBusException {
38 | super(path, wallet);
39 | this.wallet = wallet;
40 | }
41 | }
42 |
43 | public static class walletOpened extends DBusSignal {
44 | public final String wallet;
45 |
46 | /**
47 | * A wallet was opened.
48 | *
49 | * @param path The path to the object this is emitted from.
50 | * @param wallet The wallet that has been opened.
51 | * @throws DBusException Could not communicate properly with the D-Bus.
52 | */
53 | public walletOpened(String path, String wallet) throws DBusException {
54 | super(path, wallet);
55 | this.wallet = wallet;
56 | }
57 | }
58 |
59 | public static class walletAsyncOpened extends DBusSignal {
60 | public final int tId;
61 | public final int handle;
62 |
63 | /**
64 | * A wallet was opened asynchronously.
65 | *
66 | * @param path The path to the object this is emitted from.
67 | * @param tId Sequential TransactionID.
68 | * @param handle Handle to the wallet, -1 in case the unlock wallet dialog was dismissed.
69 | * @throws DBusException Could not communicate properly with the D-Bus.
70 | */
71 | public walletAsyncOpened(String path, int tId, int handle) throws DBusException {
72 | super(path, tId, handle);
73 | this.tId = tId;
74 | this.handle = handle;
75 | }
76 | }
77 |
78 | public static class walletDeleted extends DBusSignal {
79 | public final String wallet;
80 |
81 | /**
82 | * A wallet was deleted.
83 | *
84 | * @param path The path to the object this is emitted from.
85 | * @param wallet The wallet that has been deleted.
86 | * @throws DBusException Could not communicate properly with the D-Bus.
87 | */
88 | public walletDeleted(String path, String wallet) throws DBusException {
89 | super(path, wallet);
90 | this.wallet = wallet;
91 | }
92 | }
93 |
94 | public static class walletClosed extends DBusSignal {
95 | public final String wallet;
96 |
97 | /**
98 | * A wallet was closed.
99 | *
100 | * @param path The path to the object this is emitted from.
101 | * @param wallet The wallet that has been closed.
102 | * @throws DBusException Could not communicate properly with the D-Bus.
103 | */
104 | public walletClosed(String path, String wallet) throws DBusException {
105 | super(path, wallet);
106 | this.wallet = wallet;
107 | }
108 | }
109 |
110 | public static class walletClosedId extends DBusSignal {
111 | public final int handle;
112 |
113 | /**
114 | * A wallet was closed.
115 | *
116 | * @param path The path to the object this is emitted from.
117 | * @param handle Handle of the wallet.
118 | * @throws DBusException Could not communicate properly with the D-Bus.
119 | */
120 | public walletClosedId(String path, int handle) throws DBusException {
121 | super(path, handle);
122 | this.handle = handle;
123 | }
124 | }
125 |
126 | public static class allWalletsClosed extends DBusSignal {
127 | /**
128 | * All wallets were closed.
129 | *
130 | * @param path The path to the object this is emitted from.
131 | * @throws DBusException Could not communicate properly with the D-Bus.
132 | */
133 | public allWalletsClosed(String path) throws DBusException {
134 | super(path);
135 | }
136 | }
137 |
138 | public static class folderListUpdated extends DBusSignal {
139 | public final String wallet;
140 |
141 | /**
142 | * The list of folders contained in a wallet was updated.
143 | *
144 | * @param path The path to the object this is emitted from.
145 | * @param wallet The wallet in which the list of folders has been updated.
146 | * @throws DBusException Could not communicate properly with the D-Bus.
147 | */
148 | public folderListUpdated(String path, String wallet) throws DBusException {
149 | super(path, wallet);
150 | this.wallet = wallet;
151 | }
152 | }
153 |
154 | public static class folderUpdated extends DBusSignal {
155 | public final String a;
156 | public final String b;
157 |
158 | /**
159 | * The content of a folder in a wallet was updated.
160 | *
161 | * @param path The path to the object this is emitted from.
162 | * @param a The wallet that contains the folder.
163 | * @param b The folder whose content has been updated.
164 | * @throws DBusException Could not communicate properly with the D-Bus.
165 | */
166 | public folderUpdated(String path, String a, String b) throws DBusException {
167 | super(path, a, b);
168 | this.a = a;
169 | this.b = b;
170 | }
171 | }
172 |
173 | public static class applicationDisconnected extends DBusSignal {
174 | public final String wallet;
175 | public final String application;
176 |
177 | /**
178 | * An application was disconnected from a wallet.
179 | *
180 | * @param path The path to the object this is emitted from.
181 | * @param wallet The wallet the application has been disconnected from.
182 | * @param application The application that has been disconnected.
183 | * @throws DBusException Could not communicate properly with the D-Bus.
184 | */
185 | public applicationDisconnected(String path, String wallet, String application) throws DBusException {
186 | super(path, wallet, application);
187 | this.wallet = wallet;
188 | this.application = application;
189 | }
190 | }
191 |
192 | /**
193 | * Is kwallet installed?
194 | *
195 | * @return Indicator, if the kwallet daemon is up and running or not.
196 | */
197 | abstract public boolean isEnabled();
198 |
199 | /**
200 | * Open and unlock the wallet.
201 | *
202 | * @param wallet The wallet to be opened and unlocked.
203 | * @param wId The window id to associate any dialogs with. You can pass 0 if you don't have a window the password dialog should associate with.
204 | * @param appid The application that accesses the wallet.
205 | * @return Handle to the wallet or -1, if opening fails.
206 | */
207 | abstract public int open(String wallet, long wId, String appid);
208 |
209 | /**
210 | * Open and unlock the wallet with this path.
211 | *
212 | * @param path Path to the wallet.
213 | * @param wId The window id to associate any dialogs with. You can pass 0 if you don't have a window the password dialog should associate with.
214 | * @param appid The application that accesses the wallet.
215 | * @return Always 0.
216 | */
217 | abstract public int openPath(String path, long wId, String appid);
218 |
219 | /**
220 | * Open the wallet asynchronously.
221 | *
222 | * @param wallet The wallet to be opened.
223 | * @param wId The window id to associate any dialogs with. You can pass 0 if you don't have a window the password dialog should associate with.
224 | * @param appid The application that accesses the wallet.
225 | * @param handleSession Handle session with kwalletsessionstore or not.
226 | * @return Sequential TransactionID.
227 | */
228 | abstract public int openAsync(String wallet, long wId, String appid, boolean handleSession);
229 |
230 | /**
231 | * Open and unlock the wallet with this path asynchronously.
232 | *
233 | * @param path Path to the wallet.
234 | * @param wId The window id to associate any dialogs with. You can pass 0 if you don't have a window the password dialog should associate with.
235 | * @param appid The application that accesses the wallet.
236 | * @param handleSession Handle session with kwalletsessionstore or not.
237 | * @return Sequential TransactionID.
238 | */
239 | abstract public int openPathAsync(String path, long wId, String appid, boolean handleSession);
240 |
241 | /**
242 | * Close and lock the wallet. The wallet will only be closed if it is open but not in use (rare), or if it is forced closed.
243 | *
244 | * If force = true, will close it for all users. Behave. This
245 | * can break applications, and is generally intended for use by
246 | * the wallet manager app only.
247 | *
248 | * @param wallet The wallet to be closed and locked.
249 | * @param force Forced closing or not.
250 | * @return -1 if wallet does not exist, 0 if all references fom applications to the wallet have been removed.
251 | */
252 | abstract public int close(String wallet, boolean force);
253 |
254 | /**
255 | * Close and lock the wallet.
256 | *
257 | * If force = true, will close it for all users. Behave. This
258 | * can break applications, and is generally intended for use by
259 | * the wallet manager app only.
260 | *
261 | * @param handle Handle to the wallet to be closed and locked.
262 | * @param force Forced closing or not.
263 | * @param appid AppID of the app to access the wallet.
264 | * @return -1 if wallet does not exist, amount of references to the wallet fom other applications.
265 | */
266 | abstract public int close(int handle, boolean force, String appid);
267 |
268 | /**
269 | * Save to disk but leave open.
270 | *
271 | * @param handle Valid handle to the wallet to be saved.
272 | * @param appid AppID of the app to access the wallet.
273 | */
274 | @MethodNoReply
275 | abstract public void sync(int handle, String appid);
276 |
277 | /**
278 | * Physically deletes the wallet from disk.
279 | *
280 | * @param wallet The wallet to be deleted.
281 | * @return -1 if something went wrong, 0 if the wallet could be deleted.
282 | */
283 | abstract public int deleteWallet(String wallet);
284 |
285 | /**
286 | * Is the wallet open and unlocked by any application?
287 | *
288 | * @param wallet The wallet to be tested.
289 | * @return True, if the wallet is open and unlocked, false otherwise.
290 | */
291 | abstract public boolean isOpen(String wallet);
292 |
293 | /**
294 | * Is the wallet open, unlocked and has a valid handle?
295 | *
296 | * @param handle The handle to the wallet to be tested.
297 | * @return True, if the wallet is open, unlocked and the handle is valid, false otherwise.
298 | */
299 | abstract public boolean isOpen(int handle);
300 |
301 | /**
302 | * List the applications that are using the wallet.
303 | *
304 | * @param wallet The wallet to query.
305 | * @return A list of all application IDs using the wallet.
306 | */
307 | abstract public List users(String wallet);
308 |
309 | /**
310 | * Request to the wallet service to change the password of the wallet.
311 | *
312 | * @param wallet The wallet to change the password of.
313 | * @param wId The window id to associate any dialogs with. You can pass 0 if you don't have a window the password dialog should associate with.
314 | * @param appid AppID of the app to access the wallet.
315 | */
316 | abstract public void changePassword(String wallet, long wId, String appid);
317 |
318 | /**
319 | * List of all wallets.
320 | *
321 | * @return List of wallets available.
322 | */
323 | abstract public List wallets();
324 |
325 | /**
326 | * Obtain the list of all folders contained in the wallet.
327 | *
328 | * @param handle Valid handle to the wallet to be read from.
329 | * @param appid AppID of the app to access the wallet.
330 | * @return List of folders in that wallet.
331 | */
332 | abstract public List folderList(int handle, String appid);
333 |
334 | /**
335 | * Determine, if the folder exists in the wallet.
336 | *
337 | * @param handle Valid handle to the wallet to be read from.
338 | * @param folder Name of the folder.
339 | * @param appid AppID of the app to access the wallet.
340 | * @return True if the folder exists, false otherwise.
341 | */
342 | abstract public boolean hasFolder(int handle, String folder, String appid);
343 |
344 | /**
345 | * Create a folder.
346 | *
347 | * @param handle Valid handle to the wallet to write to.
348 | * @param folder Name of the folder.
349 | * @param appid AppID of the app to access the wallet.
350 | * @return True on success, false on error or in case the folder already exists.
351 | */
352 | abstract public boolean createFolder(int handle, String folder, String appid);
353 |
354 | /**
355 | * Delete a folder.
356 | *
357 | * @param handle Valid handle to the wallet to write to.
358 | * @param folder Name of the folder.
359 | * @param appid AppID of the app to access the wallet.
360 | * @return True on success, false on error.
361 | */
362 | abstract public boolean removeFolder(int handle, String folder, String appid);
363 |
364 | /**
365 | * Get a list of all the entries (keys) in the given folder.
366 | *
367 | * @param handle Valid handle to the wallet to read from.
368 | * @param folder Name of the folder.
369 | * @param appid AppID of the app to access the wallet.
370 | * @return List of entries (keys) in the folder.
371 | */
372 | abstract public List entryList(int handle, String folder, String appid);
373 |
374 | /**
375 | * Read a secret from the wallet.
376 | *
377 | * @param handle Valid handle to the wallet to read from.
378 | * @param folder Folder that contains the secret.
379 | * @param key Identifier for the secret.
380 | * @param appid AppID of the app to access the wallet.
381 | * @return The secret or an array bytes with length 0, in case there is no secret stored for that key.
382 | */
383 | abstract public byte[] readEntry(int handle, String folder, String key, String appid);
384 |
385 | /**
386 | * Read a secret of type map from the wallet.
387 | *
388 | * @param handle Valid handle to the wallet to read from.
389 | * @param folder Folder that contains the secret.
390 | * @param key Identifier for the secret.
391 | * @param appid AppID of the app to access the wallet.
392 | * @return The secret or an array bytes with length 0, in case there is no secret stored for that key.
393 | */
394 | abstract public byte[] readMap(int handle, String folder, String key, String appid);
395 |
396 | /**
397 | * Read a secret of type password from the wallet.
398 | *
399 | * @param handle Valid handle to the wallet to read from.
400 | * @param folder Folder that contains the secret.
401 | * @param key Identifier for the secret.
402 | * @param appid AppID of the app to access the wallet.
403 | * @return The secret or an empty String, in case there is no secret stored for that key.
404 | */
405 | abstract public String readPassword(int handle, String folder, String key, String appid);
406 |
407 | /*
408 | abstract public Map readEntryList(int handle, String folder, String key, String appid);
409 |
410 | abstract public Map readMapList(int handle, String folder, String key, String appid);
411 |
412 | abstract public Map readPasswordList(int handle, String folder, String key, String appid);
413 | */
414 |
415 | /**
416 | * Get a list of all the secrets in the given folder.
417 | *
418 | * @param handle Valid handle to the wallet to read from.
419 | * @param folder Folder that contains the secret(s).
420 | * @param appid AppID of the app to access the wallet.
421 | * @return Map of secrets of all types in the folder.
422 | */
423 | abstract public Map entriesList(int handle, String folder, String appid);
424 |
425 | /**
426 | * Get a list of all the secrets of type map in the given folder.
427 | *
428 | * @param handle Valid handle to the wallet to read from.
429 | * @param folder Folder that contains the secret(s).
430 | * @param appid AppID of the app to access the wallet.
431 | * @return Map of maps in the folder.
432 | */
433 | abstract public Map mapList(int handle, String folder, String appid);
434 |
435 | /**
436 | * Get a list of all the secrets of type password in the given folder.
437 | *
438 | * @param handle Valid handle to the wallet to read from.
439 | * @param folder Folder that contains the secret(s).
440 | * @param appid AppID of the app to access the wallet.
441 | * @return Map of passwords in the folder.
442 | */
443 | abstract public Map passwordList(int handle, String folder, String appid);
444 |
445 | /**
446 | * Rename an entry that contains a secret within a folder.
447 | *
448 | * @param handle Valid handle to the wallet to write to.
449 | * @param folder Folder that contains the secret.
450 | * @param oldName Old name of the entry to be changed.
451 | * @param newName New name.
452 | * @param appid AppID of the app to access the wallet.
453 | * @return 0 if renaming the entry was successful, -1 otherwise.
454 | */
455 | abstract public int renameEntry(int handle, String folder, String oldName, String newName, String appid);
456 |
457 | /**
458 | * Store a secret in the wallet. An existing secret gets overwritten.
459 | *
460 | * @param handle Valid handle to the wallet to write to.
461 | * @param folder Folder to store the secret in.
462 | * @param key Identifier for the secret.
463 | * @param value The secret itself.
464 | * @param entryType An enumerated type representing the type of the entry, e.g. 1 for password, 2 for stream, 3 for map
465 | * @param appid AppID of the app to access the wallet.
466 | * @return 0 if storing the secret was successful, -1 otherwise.
467 | */
468 | abstract public int writeEntry(int handle, String folder, String key, byte[] value, int entryType, String appid);
469 |
470 | /**
471 | * Store a secret of type stream in the wallet. An existing secret gets overwritten.
472 | *
473 | * @param handle Valid handle to the wallet to write to.
474 | * @param folder Folder to store the secret in.
475 | * @param key Identifier for the secret.
476 | * @param value The secret itself.
477 | * @param appid AppID of the app to access the wallet.
478 | * @return 0 if storing the secret was successful, -1 otherwise.
479 | */
480 | abstract public int writeEntry(int handle, String folder, String key, byte[] value, String appid);
481 |
482 | /**
483 | * Store a secret of type map in the wallet. An existing secret gets overwritten.
484 | *
485 | * @param handle Vaild handle to the wallet to write to.
486 | * @param folder Folder to store the secret in.
487 | * @param key Identifier for the secret.
488 | * @param value The secret itself.
489 | * @param appid AppID of the app to access the wallet.
490 | * @return 0 if storing the secret was successful, -1 otherwise.
491 | */
492 | abstract public int writeMap(int handle, String folder, String key, byte[] value, String appid);
493 |
494 | /**
495 | * Store a secret of type password in the wallet. An existing secret gets overwritten.
496 | *
497 | * @param handle Valid handle to the wallet to write to.
498 | * @param folder Folder to store the secret in.
499 | * @param key Identifier for the secret.
500 | * @param value The secret itself.
501 | * @param appid AppID of the app to access the wallet.
502 | * @return 0 if storing the secret was successful, -1 otherwise.
503 | */
504 | abstract public int writePassword(int handle, String folder, String key, String value, String appid);
505 |
506 | /**
507 | * Check whether a folder in a wallet contains an identifier for a secret.
508 | *
509 | * @param handle Valid handle to the wallet to read from.
510 | * @param folder Folder to search.
511 | * @param key Identifier for the secret.
512 | * @param appid AppID of the app to access the wallet.
513 | * @return True if the folder contains the key, false otherwise.
514 | */
515 | abstract public boolean hasEntry(int handle, String folder, String key, String appid);
516 |
517 | /**
518 | * Determine the type of the entry key in this folder.
519 | *
520 | * @param handle Valid handle to the wallet to read from.
521 | * @param folder Name of the folder.
522 | * @param key Identifier for the secret.
523 | * @param appid AppID of the app to access the wallet.
524 | * @return An enumerated type representing the type of the entry on creation, e.g. 1 for password, 2 for stream, 3 for map, 0 if the key was not found.
525 | */
526 | abstract public int entryType(int handle, String folder, String key, String appid);
527 |
528 | /**
529 | * Delete an identifier for a secret from the folder.
530 | *
531 | * @param handle Valid handle to the wallet to write to.
532 | * @param folder Folder to delete the key from.
533 | * @param key Identifier for the secret.
534 | * @param appid AppID of the app to access the wallet.
535 | * @return 0 if deleting the key was successful, -1 in case the wallet does not exist, -3 in case the key does not exist.
536 | */
537 | abstract public int removeEntry(int handle, String folder, String key, String appid);
538 |
539 | /**
540 | * Disconnect the application from wallet.
541 | *
542 | * @param wallet The name of the wallet to disconnect from.
543 | * @param application The name of the application to disconnect.
544 | * @return True on success, false on error.
545 | */
546 | abstract public boolean disconnectApplication(String wallet, String application);
547 |
548 | /**
549 | * Read kwalletd configuration and configure daemon accordingly.
550 | *
551 | */
552 | abstract public void reconfigure();
553 |
554 | /**
555 | * Determine, if the folder does not exist in the wallet.
556 | *
557 | * @param wallet The wallet to look into.
558 | * @param folder The folder to look for.
559 | * @return True, if the folder does not exist, false otherwise.
560 | */
561 | abstract public boolean folderDoesNotExist(String wallet, String folder);
562 |
563 | /**
564 | * Determine, if the identifier for a secret does not exist in the wallet.
565 | *
566 | * @param wallet The wallet to look into.
567 | * @param folder The folder to look into.
568 | * @param key The identifier to look for.
569 | * @return True, if the identifier does not exist, false otherwise.
570 | */
571 | abstract public boolean keyDoesNotExist(String wallet, String folder, String key);
572 |
573 | /**
574 | * Close all wallets.
575 | *
576 | */
577 | abstract public void closeAllWallets();
578 |
579 | /**
580 | * The name of the wallet used to store network passwords.
581 | *
582 | * @return Name of the wallet.
583 | */
584 | abstract public String networkWallet();
585 |
586 | /**
587 | * The name of the wallet used to store local passwords.
588 | *
589 | * @return Name of the wallet.
590 | */
591 | abstract public String localWallet();
592 |
593 | /**
594 | * Open a wallet using a pre-hashed password. This is only useful in cooperation
595 | * with the kwallet PAM module. It's also less secure than manually entering the
596 | * password as the password hash is transmitted using D-Bus.
597 | *
598 | * @param wallet The wallet to be opened.
599 | * @param passwordHash The pre-hashed password.
600 | * @param sessionTimeout Timeout after which the wallet gets closed.
601 | */
602 | @MethodNoReply
603 | abstract public void pamOpen(String wallet, byte[] passwordHash, int sessionTimeout);
604 | }
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/MapEntries.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.*;
7 | import java.util.Arrays;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.Objects;
11 |
12 | /**
13 | * KWallet allows to store secrets as byte fields, that contain maps.
14 | * This is a helper class to manage these maps.
15 | */
16 | public class MapEntries {
17 |
18 | private final Logger log = LoggerFactory.getLogger(MapEntries.class);
19 | private Map map = new HashMap<>();
20 | private final byte[] EMPTY_ENTRY = new byte[]{-1, -1, -1, -1};
21 | private final byte[] EMPTY_VALUE = new byte[]{0, 0, 0, 0};
22 |
23 | /**
24 | * Add or replace an entry to the map.
25 | *
26 | * @param key The key for the entry in the map.
27 | * @param value The secret to be stored with the key.
28 | */
29 | public void storeEntry(String key, String value) {
30 | map.put(Objects.toString(key, ""), Objects.toString(value, ""));
31 | }
32 |
33 | /**
34 | * Delete an entry from the map.
35 | *
36 | * @param key The key for the entry in the map.
37 | * @param value The secret to be deleted in conjunction with the key.
38 | */
39 | public void removeEntry(String key, String value) {
40 | map.remove(key, value);
41 | }
42 |
43 | /**
44 | * Check, whether the map contains an entry with the given key.
45 | *
46 | * @param key The key to search for.
47 | * @return True if the key was found, false otherwise.
48 | */
49 | public boolean hasKey(String key) {
50 | return map.containsKey(key);
51 | }
52 |
53 | /**
54 | * Check, whether the map contains an entry with the given key and value.
55 | *
56 | * @param key The key to search for.
57 | * @param value The value that is stored with that key.
58 | * @return True if the according entry was found, false otherwise.
59 | */
60 | public boolean hasValue(String key, String value) {
61 | return hasKey(key) && map.get(key).equals(value);
62 | }
63 |
64 | /**
65 | * Get the value of an entry for a given key.
66 | *
67 | * @param key The key to search for.
68 | * @return The value if set, an empty String otherwise.
69 | */
70 | public String getValue(String key) {
71 | return hasKey(key) && null != map.get(key) ? map.get(key) : "";
72 | }
73 |
74 | /**
75 | * Change the value of an entry in the map.
76 | *
77 | * @param key The key on which the value should be changed.
78 | * @param value The new value.
79 | * @return True, if the key exists. The value was changed then. False otherwise.
80 | */
81 | public boolean changeValue(String key, String value) {
82 | if (hasKey(key)) {
83 | storeEntry(key, value);
84 | return true;
85 | }
86 | return false;
87 | }
88 |
89 | /**
90 | * Count number of entries in the map.
91 | *
92 | * @return Number or 0 if map is empty.
93 | */
94 | public int count() {
95 | return null != map && !map.isEmpty() ? map.size() : 0;
96 | }
97 |
98 | /**
99 | * Take the intern representation of the map entries and convert it to a KWallet map compatible byte field.
100 | * @see MapEntries#setByteField(byte[])
101 | *
102 | * @return The byte field or byte[0] in case something went wrong.
103 | */
104 | public byte[] getByteField() {
105 | if (null == map || map.isEmpty()) return new byte[0];
106 | try (var b = new ByteArrayOutputStream();
107 | var s = new DataOutputStream(b)) {
108 |
109 | s.writeInt(map.size());
110 |
111 | for (var entry : map.entrySet()) {
112 | if (null == entry.getKey() || entry.getKey().isEmpty()) {
113 | s.write(EMPTY_ENTRY);
114 | s.write(EMPTY_ENTRY);
115 |
116 | } else if (null == entry.getValue() || entry.getValue().isEmpty()) {
117 | s.writeInt(entry.getKey().length() * 2);
118 | s.writeChars(entry.getKey());
119 | s.write(EMPTY_VALUE);
120 |
121 | } else {
122 | s.writeInt(entry.getKey().length() * 2);
123 | s.writeChars(entry.getKey());
124 | s.writeInt(entry.getValue().length() * 2);
125 | s.writeChars(entry.getValue());
126 | }
127 | }
128 | return b.toByteArray();
129 |
130 | } catch (IOException e) {
131 | log.error(e.toString(), e.getCause());
132 | return new byte[0];
133 | }
134 | }
135 |
136 | /**
137 | * Take a KWallet map compatible byte field and store it as a HashMap.
138 | *
139 | * @param s The byte field. Format is as follows:
140 | * {0,0,0,2, // always starts with the number of entries (int) - key/value-combinations
141 | * // followed by the entries themselves, which are _either_
142 | * 0,0,0,2, // the number of bytes for the key
143 | * 0,65, // the key as bytes
144 | * 0,0,0,2, // the number of bytes for the value
145 | * 0,66, // the value as bytes
146 | * / note: empty values are 0,0,0,0 instead of number of bytes for the key and value bytes
147 | * -1,-1,-1,-1,-1,-1,-1,-1} // _or_ an empty entry
148 | * @return True if converting the byte field succeeded without errors, false otherwise.
149 | */
150 | public boolean setByteField(byte[] s) {
151 | map = new HashMap<>();
152 | if (null == s || s.length == 0) return true;
153 |
154 | try (var b = new ByteArrayInputStream(s);
155 | var x = new DataInputStream(b)) {
156 |
157 | var mapSize = x.readInt() & 0xFF;
158 |
159 | for (var i = 0; i < mapSize; i++) {
160 | // check if the mext part is a number or an EMPTY_ENTRY
161 | var nextPart = new byte[4];
162 | for (var k = 0; k < nextPart.length; k++) {
163 | nextPart[k] = x.readByte();
164 | }
165 | if (Arrays.equals(nextPart, EMPTY_ENTRY)) {
166 | map.put("", "");
167 | x.skipBytes(4);
168 | continue;
169 | }
170 | // we have a number
171 | var keySize = fourBytesToInt(nextPart) / 2;
172 | var k = new StringBuilder();
173 |
174 | for (var j = 0; j < keySize; j++) {
175 | k.append(x.readChar());
176 | }
177 |
178 | // check if the next part is a number or an EMPTY_VALUE
179 | nextPart = new byte[4];
180 | for (var l = 0; l < nextPart.length; l++) {
181 | nextPart[l] = x.readByte();
182 | }
183 | if (Arrays.equals(nextPart, EMPTY_VALUE)) {
184 | map.put(k.toString(), "");
185 | continue;
186 | }
187 | var valueSize = fourBytesToInt(nextPart) / 2;
188 | var v = new StringBuilder();
189 | for (var j = 0; j < valueSize; j++) {
190 | v.append(x.readChar());
191 | }
192 | map.put(k.toString(), v.toString());
193 | }
194 | return true;
195 |
196 | } catch (IOException e) {
197 | log.error(e.toString(), e.getCause());
198 | return false;
199 | }
200 | }
201 |
202 | private int fourBytesToInt(byte[] b) {
203 | return ((b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3] << 0)) & 0xFF;
204 | }
205 |
206 | @Override
207 | public String toString() {
208 | var sout = new StringBuilder();
209 | var i = 1;
210 | for (Map.Entry entry : map.entrySet()) {
211 | var key = entry.getKey();
212 | if (key.isEmpty()) key = "''";
213 | var value = entry.getValue();
214 | if (value.isEmpty()) value = "''";
215 | sout.append("MapEntries (").append(i).append(") {key: ").append(key).append(", value: ").append(value).append("}\n");
216 | i++;
217 | }
218 | return sout.substring(0, sout.toString().length()-1);
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/Static.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet;
2 |
3 | import org.freedesktop.dbus.DBusPath;
4 | import org.freedesktop.dbus.ObjectPath;
5 |
6 | import java.nio.charset.StandardCharsets;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class Static {
11 |
12 | public static final String DEFAULT_WALLET = "kdewallet";
13 |
14 | public static class DBus {
15 | public static class Interfaces {
16 | public static final String DBUS_PROPERTIES = "org.freedesktop.DBus.Properties";
17 | }
18 | }
19 |
20 | public static class Service {
21 | public static final String KWALLETD5 = "org.kde.kwalletd5";
22 | public static final String KWALLETD6 = "org.kde.kwalletd6";
23 | }
24 |
25 | public static class ObjectPaths {
26 | public static final String KWALLETD5 = "/modules/kwalletd5";
27 | public static final String KWALLETD6 = "/modules/kwalletd6";
28 | }
29 |
30 | public static class Interfaces {
31 | public static final String KWALLET = "org.kde.KWallet";
32 | }
33 |
34 | public static class Convert {
35 |
36 | public static byte[] toByteArray(List list) {
37 | var result = new byte[list.size()];
38 | for (var i = 0; i < list.size(); i++) {
39 | result[i] = list.get(i);
40 | }
41 | return result;
42 | }
43 |
44 | public static String toString(byte[] bytes) {
45 | return new String(bytes, StandardCharsets.UTF_8);
46 | }
47 |
48 | public static ObjectPath toObjectPath(String path) {
49 | return new ObjectPath("", path);
50 | }
51 |
52 | public static List toStrings(List paths) {
53 | ArrayList ps = new ArrayList();
54 | for (ObjectPath p : paths) {
55 | ps.add(p.getPath());
56 | }
57 | return ps;
58 | }
59 |
60 | public static List toDBusPaths(List paths) {
61 | ArrayList ps = new ArrayList();
62 | for (ObjectPath p : paths) {
63 | ps.add(p);
64 | }
65 | return ps;
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/freedesktop/dbus/handlers/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet.freedesktop.dbus.handlers;
2 |
3 | import org.freedesktop.dbus.connections.impl.DBusConnection;
4 | import org.freedesktop.dbus.exceptions.DBusException;
5 | import org.freedesktop.dbus.types.Variant;
6 | import org.purejava.kwallet.Static;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.util.Arrays;
11 |
12 | public class MessageHandler {
13 |
14 | private static final Logger LOG = LoggerFactory.getLogger(MessageHandler.class);
15 |
16 | private DBusConnection connection;
17 |
18 | public MessageHandler(DBusConnection connection) {
19 | this.connection = connection;
20 |
21 | if (this.connection != null) {
22 | this.connection.setWeakReferences(true);
23 | Runtime.getRuntime().addShutdownHook(new Thread(() ->
24 | this.connection.disconnect()
25 | ));
26 | }
27 | }
28 |
29 | public Object[] send(String service, String path, String iface, String method, String signature, Object... args) {
30 | try {
31 | var msgFactory = connection.getMessageFactory();
32 | var message = msgFactory.createMethodCall(service, path, iface, method, (byte) 0, signature, args);
33 |
34 | if (LOG.isTraceEnabled()) LOG.trace(String.valueOf(message));
35 | connection.sendMessage(message);
36 |
37 | var response = message.getReply(2000L);
38 | if (LOG.isTraceEnabled()) LOG.trace(String.valueOf(response));
39 |
40 | Object[] parameters = null;
41 | if (response != null) {
42 | parameters = response.getParameters();
43 | LOG.debug(Arrays.deepToString(parameters));
44 | }
45 |
46 | if (response instanceof org.freedesktop.dbus.messages.Error) {
47 | var error = response.getName();
48 | switch (error) {
49 | case "org.freedesktop.DBus.Error.NoReply",
50 | "org.freedesktop.DBus.Error.UnknownMethod",
51 | "org.freedesktop.dbus.exceptions.NotConnected" -> {
52 | LOG.debug(error);
53 | return null;
54 | }
55 | default -> throw new DBusException(error);
56 | }
57 | }
58 | return parameters;
59 |
60 | } catch (DBusException e) {
61 | LOG.error("Unexpected D-Bus response:", e);
62 | }
63 |
64 | return null;
65 | }
66 |
67 | public Variant getProperty(String service, String path, String iface, String property) {
68 | var response = send(service, path, Static.DBus.Interfaces.DBUS_PROPERTIES,
69 | "Get", "ss", iface, property);
70 | return response == null ? null : (Variant) response[0];
71 | }
72 |
73 | public Variant getAllProperties(String service, String path, String iface) {
74 | var response = send(service, path, Static.DBus.Interfaces.DBUS_PROPERTIES,
75 | "GetAll", "ss", iface);
76 | return response == null ? null : (Variant) response[0];
77 | }
78 |
79 | public void setProperty(String service, String path, String iface, String property, Variant value) {
80 | send(service, path, Static.DBus.Interfaces.DBUS_PROPERTIES,
81 | "Set", "ssv", iface, property, value);
82 | }
83 |
84 | public DBusConnection getConnection() {
85 | return connection;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/freedesktop/dbus/handlers/Messaging.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet.freedesktop.dbus.handlers;
2 |
3 | import org.freedesktop.dbus.ObjectPath;
4 | import org.freedesktop.dbus.connections.impl.DBusConnection;
5 | import org.freedesktop.dbus.messages.DBusSignal;
6 | import org.freedesktop.dbus.types.Variant;
7 | import org.purejava.kwallet.Static;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.util.List;
12 |
13 | abstract public class Messaging {
14 |
15 | private static final Logger LOG = LoggerFactory.getLogger(Messaging.class);
16 | private DBusConnection connection;
17 | private MessageHandler msg;
18 | private SignalHandler sh = SignalHandler.getInstance();
19 | private String serviceName;
20 | private String objectPath;
21 | private String interfaceName;
22 |
23 | public Messaging(DBusConnection connection, List> signals,
24 | String serviceName, String objectPath, String interfaceName) {
25 | this.connection = connection;
26 | this.msg = new MessageHandler(connection);
27 | if (null != signals) {
28 | this.sh.connect(connection, signals);
29 | }
30 | if (null == serviceName || null == objectPath) {
31 | LOG.error("Kwallet daemon not initialized properly");
32 | }
33 | this.serviceName = serviceName;
34 | this.objectPath = objectPath;
35 | this.interfaceName = interfaceName;
36 | }
37 |
38 | public Object[] send(String method) {
39 | return msg.send(serviceName, objectPath, interfaceName, method, "");
40 | }
41 |
42 | public Object[] send(String method, String signature, Object... arguments) {
43 | return msg.send(serviceName, objectPath, interfaceName, method, signature, arguments);
44 | }
45 |
46 | protected Variant getProperty(String property) {
47 | return msg.getProperty(serviceName, objectPath, interfaceName, property);
48 | }
49 |
50 | protected Variant getAllProperties() {
51 | return msg.getAllProperties(serviceName, objectPath, interfaceName);
52 | }
53 |
54 | protected void setProperty(String property, Variant value) {
55 | msg.setProperty(serviceName, objectPath, interfaceName, property, value);
56 | }
57 |
58 | public String getServiceName() {
59 | return serviceName;
60 | }
61 |
62 | public String getObjectPath() {
63 | return objectPath;
64 | }
65 |
66 | public ObjectPath getPath() {
67 | return Static.Convert.toObjectPath(objectPath);
68 | }
69 |
70 | public String getInterfaceName() {
71 | return interfaceName;
72 | }
73 |
74 | public MessageHandler getMessageHandler() {
75 | return msg;
76 | }
77 |
78 | public SignalHandler getSignalHandler() {
79 | return sh;
80 | }
81 |
82 | public DBusConnection getConnection() {
83 | return connection;
84 | }
85 |
86 | }
--------------------------------------------------------------------------------
/src/main/java/org/purejava/kwallet/freedesktop/dbus/handlers/SignalHandler.java:
--------------------------------------------------------------------------------
1 | package org.purejava.kwallet.freedesktop.dbus.handlers;
2 |
3 | import org.freedesktop.dbus.connections.impl.DBusConnection;
4 | import org.freedesktop.dbus.exceptions.DBusException;
5 | import org.freedesktop.dbus.interfaces.DBusSigHandler;
6 | import org.freedesktop.dbus.messages.DBusSignal;
7 | import org.purejava.kwallet.KWallet;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.beans.PropertyChangeListener;
12 | import java.beans.PropertyChangeSupport;
13 | import java.time.Duration;
14 | import java.util.*;
15 | import java.util.concurrent.*;
16 | import java.util.stream.Collectors;
17 |
18 | public class SignalHandler implements DBusSigHandler {
19 |
20 | private static SignalHandler instance = new SignalHandler();
21 |
22 | private static final Logger LOG = LoggerFactory.getLogger(SignalHandler.class);
23 |
24 | private PropertyChangeSupport support;
25 | private DBusConnection connection = null;
26 | private List> registered = new ArrayList();
27 | private DBusSignal[] handled = new DBusSignal[250];
28 | private int count = 0;
29 |
30 | private SignalHandler() {
31 | support = new PropertyChangeSupport(this);
32 | }
33 |
34 | public static SignalHandler getInstance() {
35 | return instance;
36 | }
37 |
38 | public void addPropertyChangeListener(PropertyChangeListener pcl) {
39 | support.addPropertyChangeListener(pcl);
40 | }
41 |
42 | public void removePropertyChangeListener(PropertyChangeListener pcl) {
43 | support.removePropertyChangeListener(pcl);
44 | }
45 |
46 | public void connect(DBusConnection connection, List> signals) {
47 | if (null == this.connection) {
48 | this.connection = connection;
49 | }
50 | if (signals != null) {
51 | try {
52 | for (Class sc : signals) {
53 | if (!registered.contains(sc)) {
54 | connection.addSigHandler(sc, this);
55 | registered.add(sc);
56 | }
57 | }
58 | } catch (DBusException e) {
59 | LOG.error(e.toString(), e.getCause());
60 | }
61 | }
62 | }
63 |
64 | @Override
65 | public void handle(DBusSignal s) {
66 |
67 | Collections.rotate(Arrays.asList(handled), 1);
68 | handled[0] = s;
69 | count += 1;
70 |
71 | if (s instanceof KWallet.walletOpened wo) {
72 | support.firePropertyChange("KWallet.walletOpened", null, wo.wallet);
73 | LOG.info("Received signal KWallet.walletOpened: {}", wo.wallet);
74 | } else if (s instanceof KWallet.walletAsyncOpened wo) {
75 | support.firePropertyChange("KWallet.walletAsyncOpened", null, wo.handle);
76 | LOG.info("Received signal KWallet.walletAsyncOpened: {TransactionID: {}, handle: {}}", wo.tId, wo.handle);
77 | } else if (s instanceof KWallet.walletDeleted wd) {
78 | support.firePropertyChange("KWallet.walletDeleted", null, wd.wallet);
79 | LOG.info("Received signal KWallet.walletDeleted: {}", wd.wallet);
80 | } else if (s instanceof KWallet.walletClosedId wc) {
81 | support.firePropertyChange("KWallet.walletClosedId", null, wc.handle);
82 | LOG.info("Received signal KWallet.walletClosedId: {}", wc.handle);
83 | } else if (s instanceof KWallet.walletClosed wc) {
84 | support.firePropertyChange("KWallet.walletClosed", null, wc.wallet);
85 | LOG.info("Received signal KWallet.walletClosed: {}", wc.wallet);
86 | } else if (s instanceof KWallet.allWalletsClosed) {
87 | support.firePropertyChange("KWallet.allWalletsClosed", null, s.getPath());
88 | LOG.info("Received signal KWallet.allWalletsClosed: {}", s.getPath());
89 | } else if (s instanceof KWallet.folderListUpdated flu) {
90 | support.firePropertyChange("KWallet.folderListUpdated", null, flu.wallet);
91 | LOG.info("Received signal KWallet.folderListUpdated: {}", flu.wallet);
92 | } else if (s instanceof KWallet.folderUpdated fu) {
93 | support.firePropertyChange("KWallet.folderUpdated", null, fu.a + "/" + fu.b);
94 | LOG.info("Received signal KWallet.folderUpdated: {wallet: {}, folder: {}}", fu.a, fu.b);
95 | } else if (s instanceof KWallet.applicationDisconnected ad) {
96 | support.firePropertyChange("KWallet.applicationDisconnected", null, ad.application + "/" + ad.wallet);
97 | LOG.info("Received signal KWallet.applicationDisconnected: {application: {}, wallet: {}}", ad.application, ad.wallet);
98 | } else if (s instanceof KWallet.walletListDirty) {
99 | support.firePropertyChange("KWallet.walletListDirty", null, s.getPath());
100 | LOG.debug("Received signal KWallet.walletListDirty: {}", s.getPath());
101 | } else if (s instanceof KWallet.walletCreated wc) {
102 | support.firePropertyChange("KWallet.walletCreated", null, wc.wallet);
103 | LOG.info("Received signal KWallet.walletCreated: {}", wc.wallet);
104 | } else {
105 | LOG.warn("Received unknown signal: {} {{}}", s.getClass(), s);
106 | }
107 | }
108 |
109 | public DBusSignal[] getHandledSignals() {
110 | return handled;
111 | }
112 |
113 | public List getHandledSignals(Class s) {
114 | return Arrays.stream(handled)
115 | .filter(Objects::nonNull)
116 | .filter(signal -> signal.getClass().equals(s))
117 | .map(signal -> (S) signal)
118 | .collect(Collectors.toList());
119 | }
120 |
121 | public List getHandledSignals(Class s, String path) {
122 | return Arrays.stream(handled)
123 | .filter(Objects::nonNull)
124 | .filter(signal -> signal.getClass().equals(s))
125 | .filter(signal -> signal.getPath().equals(path))
126 | .map(signal -> (S) signal)
127 | .collect(Collectors.toList());
128 | }
129 |
130 | public int getCount() {
131 | return count;
132 | }
133 |
134 | public DBusSignal getLastHandledSignal() {
135 | return handled.length > 0 ? handled[0] : null;
136 | }
137 |
138 | public S getLastHandledSignal(Class s) {
139 | return getHandledSignals(s).isEmpty() ? null : getHandledSignals(s).get(0);
140 | }
141 |
142 | public S getLastHandledSignal(Class s, String path) {
143 | return getHandledSignals(s, path).isEmpty() ? null : getHandledSignals(s, path).get(0);
144 | }
145 |
146 | /**
147 | * @deprecated Please use {@link #addPropertyChangeListener(PropertyChangeListener)} instead
148 | */
149 | @Deprecated
150 | public S await(Class s, String path, Callable action) {
151 | final Duration timeout = Duration.ofSeconds(120);
152 | return await(s, path, action, timeout);
153 | }
154 |
155 | /**
156 | * @deprecated Please use {@link #addPropertyChangeListener(PropertyChangeListener)} instead
157 | */
158 | @Deprecated
159 | public S await(Class s, String path, Callable action, Duration timeout) {
160 | final int init = getCount();
161 |
162 | try {
163 | action.call();
164 | } catch (Exception e) {
165 | LOG.error(e.toString(), e.getCause());
166 | }
167 |
168 | var executor = Executors.newSingleThreadExecutor();
169 |
170 | LOG.info("Await signal {}" + "({}) within {} seconds.", s.getName(), path, timeout.getSeconds());
171 |
172 | final Future handler = executor.submit((Callable) () -> {
173 | var await = init;
174 | List signals = null;
175 | while (await == init) {
176 | if (Thread.currentThread().isInterrupted()) return null;
177 | Thread.currentThread().sleep(50L);
178 | signals = getHandledSignals(s, path);
179 | await = getCount();
180 | }
181 | if (!signals.isEmpty()) {
182 | return signals.get(0);
183 | } else {
184 | return null;
185 | }
186 | });
187 |
188 | try {
189 | return handler.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
190 | } catch (TimeoutException | InterruptedException | ExecutionException e) {
191 | handler.cancel(true);
192 | LOG.warn(e.toString(), e.getCause());
193 | } finally {
194 | executor.shutdownNow();
195 | }
196 |
197 | return null;
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/test/java/org/purejava/Context.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.freedesktop.dbus.connections.impl.DBusConnection;
4 | import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder;
5 | import org.freedesktop.dbus.exceptions.DBusException;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class Context {
10 |
11 | private static final Logger LOG = LoggerFactory.getLogger(Context.class);
12 |
13 | public DBusConnection connection = null;
14 |
15 | public void ensureService() {
16 | try {
17 | connection = DBusConnectionBuilder.forSessionBus().withShared(false).build();
18 | } catch (DBusException e) {
19 | LOG.error(e.toString(), e.getCause());
20 | }
21 | }
22 |
23 | public void after() {
24 | try {
25 | connection.disconnect();
26 | Thread.sleep(150L);
27 | } catch (InterruptedException e) {
28 | LOG.error(e.toString(), e.getCause());
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/test/java/org/purejava/KDEWalletTest.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.freedesktop.dbus.exceptions.DBusException;
4 | import org.freedesktop.dbus.interfaces.DBus;
5 | import org.junit.jupiter.api.*;
6 | import org.purejava.kwallet.Static;
7 | import org.purejava.kwallet.KDEWallet;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.beans.PropertyChangeEvent;
12 | import java.beans.PropertyChangeListener;
13 | import java.util.Arrays;
14 | import java.util.List;
15 |
16 | import static org.junit.jupiter.api.Assertions.assertEquals;
17 | import static org.junit.jupiter.api.Assertions.assertTrue;
18 |
19 | public class KDEWalletTest implements PropertyChangeListener {
20 | private static final Logger LOG = LoggerFactory.getLogger(KDEWalletTest.class);
21 | private Context context;
22 | private int handle = -1;
23 |
24 | @BeforeEach
25 | public void beforeEach(TestInfo info) {
26 | context = new Context();
27 | context.ensureService();
28 | }
29 |
30 | @AfterEach
31 | public void afterEach() {
32 | context.after();
33 | }
34 |
35 | @Test
36 | @Order(1)
37 | @DisplayName("Checking availability of kwallet daemon...")
38 | public void isEnabled() {
39 | try {
40 | var bus = context.connection.getRemoteObject("org.freedesktop.DBus",
41 | "/org/freedesktop/DBus", DBus.class);
42 | assertTrue (Arrays.asList(bus.ListActivatableNames()).contains("org.kde.kwalletd5")
43 | || Arrays.asList(bus.ListActivatableNames()).contains("org.kde.kwalletd6"));
44 | } catch (DBusException e) {
45 | LOG.error(e.toString(), e.getCause());
46 | }
47 | }
48 |
49 | @Test
50 | @Order(2)
51 | @DisplayName("Checking availability of wallets...")
52 | public void wallets() {
53 | var kwallet = new KDEWallet(context.connection);
54 | var response = kwallet.send("wallets");
55 | var walletNames = (List) response[0];
56 | assertTrue(walletNames.size() > 0);
57 | assertEquals(walletNames.get(0), Static.DEFAULT_WALLET);
58 | LOG.info("Found '{}' as first wallet.", walletNames.get(0));
59 | }
60 |
61 | @Test
62 | @Order(3)
63 | @DisplayName("Testing create folder functionality in locked kdewallet...")
64 | void testCreateFolder() throws InterruptedException {
65 | var kwallet = new KDEWallet(context.connection);
66 | var wallet = Static.DEFAULT_WALLET;
67 | var wId = 0;
68 | var appid = "Tester";
69 | kwallet.getSignalHandler().addPropertyChangeListener(this);
70 | kwallet.openAsync(wallet, wId, appid, false);
71 | LOG.info("You have 10 seconds to enter the password :)");
72 | Thread.sleep(10000L); // give me 10 seconds to enter the password
73 | assertTrue(handle > 0);
74 | if (handle > 0) LOG.info("Wallet '{}' successfully opened.", Static.DEFAULT_WALLET);
75 | if (handle > 0) LOG.info("Received handle: {}.", handle);
76 | var folder = "Test-Folder";
77 | var created = kwallet.createFolder(handle, folder, appid);
78 | assertTrue(created);
79 | LOG.info("Folder '{}' successfully created.", folder);
80 | var removed = kwallet.removeFolder(handle, folder, appid);
81 | assertTrue(removed);
82 | LOG.info("Folder '{}' successfully deleted.", folder);
83 | }
84 |
85 | @Override
86 | public void propertyChange(PropertyChangeEvent event) {
87 | if (event.getPropertyName().equals("KWallet.walletAsyncOpened")) handle = (int) event.getNewValue();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/test/java/org/purejava/KDEWalletTest1.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.junit.jupiter.api.*;
4 | import org.purejava.kwallet.Static;
5 | import org.purejava.kwallet.KDEWallet;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import static org.junit.jupiter.api.Assertions.assertEquals;
10 | import static org.junit.jupiter.api.Assertions.assertTrue;
11 |
12 | public class KDEWalletTest1 {
13 | private static final Logger LOG = LoggerFactory.getLogger(KDEWalletTest1.class);
14 | private Context context;
15 |
16 | @BeforeEach
17 | public void beforeEach(TestInfo info) {
18 | context = new Context();
19 | context.ensureService();
20 | }
21 |
22 | @AfterEach
23 | public void afterEach() {
24 | context.after();
25 | }
26 |
27 | @Test
28 | @Order(4)
29 | @DisplayName("Testing password functionality in unlocked kdewallet...")
30 | void testPassword() {
31 | var kwallet = new KDEWallet(context.connection);
32 | var wallet = Static.DEFAULT_WALLET;
33 | var wId = 0;
34 | var appid = "Tester";
35 | var response = kwallet.send("open", "sxs", wallet, wId, appid);
36 | assertTrue(kwallet.isOpen(wallet));
37 | var handle = (int) response[0];
38 | assertTrue(handle > 0);
39 | LOG.info("Wallet '{}' successfully opened.", Static.DEFAULT_WALLET);
40 | LOG.info("Received handle: {}.", handle);
41 | var folder = "Test-Folder";
42 | response = kwallet.send("createFolder", "iss", handle, folder, appid);
43 | var folderCreated = (boolean) response[0];
44 | assertTrue(folderCreated);
45 | LOG.info("Folder '{}' successfully created.", folder);
46 | var key = "PW1";
47 | var value = "secret1";
48 | response = kwallet.send("writePassword", "issss", handle, folder, key, value, appid);
49 | var secretStored = (int) response[0];
50 | assertEquals(secretStored, 0);
51 | if (secretStored == 0) LOG.info("Secret '{}' successfully stored.", value);
52 | response = kwallet.send("readPassword", "isss", handle, folder, key, appid);
53 | var secretRead = (String) response[0];
54 | assertEquals(secretRead, value);
55 | if (secretRead.equals(value)) LOG.info("Secret '{}' successfully retrieved.", value);
56 | response = kwallet.send("hasEntry", "isss", handle, folder, key, appid);
57 | var keyFound = (boolean) response[0];
58 | assertTrue(keyFound);
59 | LOG.info("Folder '{}' has key '{}'.", folder, key);
60 | response = kwallet.send("removeEntry", "isss", handle, folder, key, appid);
61 | var keyRemoved = (int) response[0];
62 | assertEquals(keyRemoved, 0);
63 | if (keyRemoved == 0) LOG.info("Key '{}' successfully removed from folder '{}'.", key, folder);
64 | response = kwallet.send("removeFolder", "iss", handle, folder, appid);
65 | var folderRemoved = (boolean) response[0];
66 | assertTrue(folderRemoved);
67 | LOG.info("Folder '{}' successfully deleted.", folder);
68 | response = kwallet.send("close", "ibs", handle, false, appid);
69 | var walletClosedId = (int) response[0];
70 | assertTrue(walletClosedId != -1);
71 | LOG.info("Wallet '{}' with handle '{}' successfully closed.", Static.DEFAULT_WALLET, handle);
72 | }
73 | }
--------------------------------------------------------------------------------
/src/test/java/org/purejava/KDEWalletTest2.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.junit.jupiter.api.*;
4 | import org.purejava.kwallet.Static;
5 | import org.purejava.kwallet.KDEWallet;
6 | import org.purejava.kwallet.MapEntries;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.util.List;
11 | import java.util.stream.Collectors;
12 | import java.util.stream.IntStream;
13 | import java.util.stream.Stream;
14 |
15 | import static org.junit.jupiter.api.Assertions.*;
16 |
17 | public class KDEWalletTest2 {
18 | private static final Logger LOG = LoggerFactory.getLogger(KDEWalletTest2.class);
19 | private Context context;
20 |
21 | @BeforeEach
22 | public void beforeEach(TestInfo info) {
23 | context = new Context();
24 | context.ensureService();
25 | }
26 |
27 | @AfterEach
28 | public void afterEach() {
29 | context.after();
30 | }
31 |
32 | @Test
33 | @Order(5)
34 | @DisplayName("Testing write entry functionality in unlocked kdewallet...")
35 | void testWriteEntry() {
36 | var kwallet = new KDEWallet(context.connection);
37 | var wallet = Static.DEFAULT_WALLET;
38 | var wId = 0;
39 | var appid = "Tester";
40 | var response = kwallet.send("open", "sxs", wallet, wId, appid);
41 | var handle = (int) response[0];
42 | assertTrue(handle > 0);
43 | LOG.info("Wallet '{}' successfully opened.", Static.DEFAULT_WALLET);
44 | LOG.info("Received handle: {}.", handle);
45 | var folder = "Test-Folder";
46 | response = kwallet.send("createFolder", "iss", handle, folder, appid);
47 | var folderCreated = (boolean) response[0];
48 | assertTrue(folderCreated);
49 | LOG.info("Folder '{}' successfully created.", folder);
50 | var key1 = "PW1";
51 | var password = "password".getBytes();
52 | response = kwallet.send("writeEntry", "issays", handle, folder, key1, password, appid);
53 | var result = (int) response[0];
54 | assertEquals(result, 0);
55 | if (result == 0) LOG.info("Secret '{}' with with key '{}' successfully stored in folder '{}'.", new String(password), key1, folder);
56 | var key2 = "Map";
57 | var map = new byte[]{0,0,0,2,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,2,0,65,0,0,0,2,0,66};
58 | var me = new MapEntries();
59 | me.setByteField(map);
60 | response = kwallet.send("writeEntry", "issayis", handle, folder, key2, map, 3, appid);
61 | result = (int) response[0];
62 | assertEquals(result, 0);
63 | if (result == 0) LOG.info("Map with with key '{}' successfully stored in folder '{}'.", key2, folder);
64 | response = kwallet.send("entryList", "iss", handle, folder, appid);
65 | var listOfEntries = (List) response[0];
66 | assertEquals(listOfEntries.size(), 2);
67 | assertEquals(listOfEntries.get(0), "Map");
68 | assertEquals(listOfEntries.get(1), "PW1");
69 | LOG.info("Found this list of entries: {}.", listOfEntries);
70 | response = kwallet.send("entryType", "isss", handle, folder, key2, appid);
71 | var entryType = (int) response[0];
72 | assertEquals(entryType, 3);
73 | LOG.info("Type of entry for map is: {}.", entryType);
74 | response = kwallet.send("readEntry", "isss", handle, folder, key1, appid);
75 | var objectList = (List>) response[0];
76 | var entry = new byte[objectList.size()];
77 | IntStream.range(0, objectList.size()).forEach(i -> entry[i] = (Byte) objectList.get(i));
78 | assertEquals(new String(entry), "password");
79 | LOG.info("Raw data from secret successfully retrieved: {}.", new String(entry));
80 | LOG.info(me.toString());
81 | assertEquals(me.count(), 2);
82 | assertTrue(me.hasKey("A"));
83 | assertTrue(me.hasValue("A","B"));
84 | me.changeValue("A","C");
85 | assertTrue(me.hasValue("A","C"));
86 | LOG.info("Value successfully changed for key 'A' from 'B' to '{}'.", me.getValue("A"));
87 | me.storeEntry("D",null);
88 | assertTrue(me.hasKey("D"));
89 | assertTrue(me.hasValue("D",""));
90 | LOG.info("Entry with key 'D' and value '' successfully stored.");
91 | LOG.info(me.toString());
92 | assertEquals(me.count(),3);
93 | me.removeEntry("A","C");
94 | me.removeEntry("D","");
95 | assertFalse(me.hasKey("D"));
96 | assertFalse(me.hasValue("D", ""));
97 | assertEquals(me.count(), 1);
98 | LOG.info("Entries with keys 'A' and 'D' successfully removed.");
99 | response = kwallet.send("writeEntry", "issayis", handle, folder, key2, me.getByteField(), 3, appid);
100 | result = (int) response[0];
101 | assertEquals(result, 0);
102 | if (result == 0) LOG.info("Map with with key '{}' successfully updated in folder '{}'.", key2, folder);
103 | var longString = Stream.iterate("A", s -> s).limit(64).collect(Collectors.joining());
104 | me.storeEntry("E", longString);
105 | response = kwallet.send("writeEntry", "issayis", handle, folder, key2, me.getByteField(), 3, appid);
106 | result = (int) response[0];
107 | assertEquals(result, 0);
108 | response = kwallet.send("readMap", "isss", handle, folder, key2, appid);
109 | var objectListFromResponse = (List>) response[0];
110 | var rm = new byte[objectListFromResponse.size()];
111 | IntStream.range(0, objectListFromResponse.size()).forEach(i -> rm[i] = (Byte) objectListFromResponse.get(i));
112 | me.setByteField(rm);
113 | assertTrue(me.hasValue("E", longString));
114 | LOG.info("Successfully stored and retrieved value '{}' with a length gt 63.", me.getValue("E"));
115 | var newName = "newName";
116 | response = kwallet.send("renameEntry", "issss", handle, folder, key1, newName, appid);
117 | var renaming = (int) response[0];
118 | assertTrue(renaming != -1);
119 | LOG.info("Entry successfully renamed to: '{}'.", newName);
120 | response = kwallet.send("removeFolder", "iss", handle, folder, appid);
121 | var folderRemoved = (boolean) response[0];
122 | assertTrue(folderRemoved);
123 | LOG.info("Folder '{}' successfully deleted.", folder);
124 | response = kwallet.send("close", "ibs", handle, false, appid);
125 | var walletClosedId = (int) response[0];
126 | assertTrue(walletClosedId != -1);
127 | LOG.info("Wallet '{}' with handle '{}' successfully closed.", Static.DEFAULT_WALLET, handle);
128 | }
129 | }
--------------------------------------------------------------------------------
/src/test/java/org/purejava/KDEWalletTest3.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.junit.jupiter.api.*;
4 | import org.purejava.kwallet.Static;
5 | import org.purejava.kwallet.KDEWallet;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import static org.junit.jupiter.api.Assertions.assertEquals;
10 | import static org.junit.jupiter.api.Assertions.assertTrue;
11 |
12 | public class KDEWalletTest3 {
13 | private static final Logger LOG = LoggerFactory.getLogger(KDEWalletTest3.class);
14 | private Context context;
15 |
16 | @BeforeEach
17 | public void beforeEach(TestInfo info) {
18 | context = new Context();
19 | context.ensureService();
20 | }
21 |
22 | @AfterEach
23 | public void afterEach() {
24 | context.after();
25 | }
26 |
27 | @Test
28 | @Order(6)
29 | @DisplayName("Testing entries list functionalities in unlocked kdewallet...")
30 | void testWriteEntry() {
31 | var kwallet = new KDEWallet(context.connection);
32 | var wallet = Static.DEFAULT_WALLET;
33 | var wId = 0;
34 | var appid = "Tester";
35 | var handle = kwallet.open(wallet, wId, appid);
36 | assertTrue(handle > 0);
37 | LOG.info("Wallet '{}' successfully opened.", Static.DEFAULT_WALLET);
38 | LOG.info("Received handle: {}.", handle);
39 | var folder = "Test-Folder";
40 | var folderCreated = kwallet.createFolder(handle, folder, appid);
41 | assertTrue(folderCreated);
42 | LOG.info("Folder '{}' successfully created.", folder);
43 | var key1 = "PW1";
44 | var password = "password";
45 | var result = kwallet.writePassword(handle, folder, key1, password, appid);
46 | assertEquals(result, 0);
47 | if (result == 0) LOG.info("Secret '{}' with with key '{}' successfully stored in folder '{}'.", password, key1, folder);
48 | var key2 = "PW2";
49 | var password2 = "password2";
50 | result = kwallet.writePassword(handle, folder, key2, password2, appid);
51 | assertEquals(result, 0);
52 | if (result == 0) LOG.info("Secret '{}' with with key '{}' successfully stored in folder '{}'.", password2, key2, folder);
53 | var key3 = "Map1";
54 | var map = new byte[]{0,0,0,2,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,2,0,65,0,0,0,2,0,66};
55 | result = kwallet.writeMap(handle, folder, key3, map, appid);
56 | assertEquals(result, 0);
57 | if (result == 0) LOG.info("Secret as map with key '{}' successfully stored in folder '{}'.", key3, folder);
58 | var key4 = "Stream1";
59 | var stream = "password3".getBytes();
60 | result = kwallet.writeEntry(handle, folder, key4, stream, appid);
61 | assertEquals(result, 0);
62 | if (result == 0) LOG.info("Secret '{}' with with key '{}' successfully stored in folder '{}'.", new String(stream), key4, folder);
63 | var el = kwallet.entriesList(handle, folder, appid);
64 | assertEquals(el.size(),4);
65 | var ml = kwallet.mapList(handle, folder, appid);
66 | assertEquals(ml.size(),1);
67 | var pl = kwallet.passwordList(handle, folder, appid);
68 | assertEquals(pl.size(),2);
69 | var p2 = pl.get("PW2");
70 | assertEquals(p2,"password2");
71 | LOG.info("Password list {} contains secret '{}' with key '{}'.", pl, password2, key2);
72 | result = kwallet.removeEntry(handle, folder, key2, appid);
73 | assertEquals(result, 0);
74 | result = kwallet.removeEntry(handle, folder, key1, appid);
75 | assertEquals(result, 0);
76 | pl = kwallet.passwordList(handle, folder, appid);
77 | assertEquals(pl.size(), 0);
78 | var folderRemoved = kwallet.removeFolder(handle, folder, appid);
79 | assertTrue(folderRemoved);
80 | LOG.info("Folder '{}' successfully deleted.", folder);
81 | var walletClosedId = kwallet.close(handle, false, appid);
82 | assertTrue(walletClosedId != -1);
83 | LOG.info("Wallet '{}' with handle '{}' successfully closed.", Static.DEFAULT_WALLET, handle);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/org/purejava/KDEWalletTest4.java:
--------------------------------------------------------------------------------
1 | package org.purejava;
2 |
3 | import org.junit.jupiter.api.*;
4 | import org.purejava.kwallet.Static;
5 | import org.purejava.kwallet.KDEWallet;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.beans.PropertyChangeEvent;
10 | import java.beans.PropertyChangeListener;
11 |
12 | import static org.junit.jupiter.api.Assertions.*;
13 |
14 | public class KDEWalletTest4 implements PropertyChangeListener {
15 | private static final Logger LOG = LoggerFactory.getLogger(KDEWalletTest4.class);
16 | private Context context;
17 | private int handle = -1;
18 |
19 | @BeforeEach
20 | public void beforeEach(TestInfo info) {
21 | context = new Context();
22 | context.ensureService();
23 | }
24 |
25 | @AfterEach
26 | public void afterEach() {
27 | context.after();
28 | }
29 |
30 | @Test
31 | @Order(7)
32 | @DisplayName("Checking availability of signals for locked wallet ...")
33 | public void testSignals() throws InterruptedException {
34 | var kwallet = new KDEWallet(context.connection);
35 | var wallet = Static.DEFAULT_WALLET;
36 | var wId = 0;
37 | var appid = "Tester";
38 | kwallet.getSignalHandler().addPropertyChangeListener(this);
39 | assertFalse(kwallet.isOpen(wallet));
40 | kwallet.openAsync(wallet, wId, appid, false);
41 | LOG.info("You have 10 seconds to enter the password :)");
42 | Thread.sleep(10000L);
43 | assertTrue(handle > 0);
44 | LOG.info("Wallet '{}' successfully opened.", Static.DEFAULT_WALLET);
45 | var walletClosedId = kwallet.close(handle, true, appid);
46 | assertTrue(walletClosedId != -1);
47 | LOG.info("Wallet '{}' with handle '{}' successfully closed.", Static.DEFAULT_WALLET, handle);
48 | }
49 |
50 | @Override
51 | public void propertyChange(PropertyChangeEvent event) {
52 | switch (event.getPropertyName()) {
53 | case "KWallet.walletAsyncOpened":
54 | handle = (int) event.getNewValue();
55 | break;
56 | case "KWallet.walletClosedId":
57 | var closeHandle = (int) event.getNewValue();
58 | assertEquals(closeHandle, handle);
59 | LOG.info("Received signal 'KWallet.walletClosedId' with handle '{}'.", closeHandle);
60 | break;
61 | case "KWallet.walletClosed":
62 | try {
63 | var wallet = (String) event.getNewValue();
64 | assertEquals(wallet, Static.DEFAULT_WALLET);
65 | LOG.info("Received signal 'KWallet.walletClosed' for wallet '{}'.", wallet);
66 | } catch (ClassCastException ex) {
67 | // ToDo handling overloaded signal here. Remove, when walletClosed(String path, int handle) got removed from kwallet.
68 | }
69 | break;
70 | default:
71 | break;
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/src/test/resources/org.freedesktop.DBus.Introspectable.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/test/resources/org.freedesktop.DBus.Peer.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/test/resources/org.freedesktop.DBus.Properties.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/test/resources/org.kde.KWallet.nodeprecated.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
--------------------------------------------------------------------------------
/src/test/resources/org.kde.KWallet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
--------------------------------------------------------------------------------
/src/test/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | org.slf4j.simpleLogger.defaultLogLevel=info
--------------------------------------------------------------------------------