1 package org
.asamk
.signal
.manager
.storage
.messageCache
;
3 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientId
;
4 import org
.asamk
.signal
.manager
.util
.IOUtils
;
5 import org
.asamk
.signal
.manager
.util
.MessageCacheUtils
;
6 import org
.slf4j
.Logger
;
7 import org
.slf4j
.LoggerFactory
;
8 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceEnvelope
;
11 import java
.io
.IOException
;
12 import java
.nio
.file
.Files
;
13 import java
.util
.Arrays
;
14 import java
.util
.Collections
;
15 import java
.util
.Objects
;
16 import java
.util
.stream
.Collectors
;
17 import java
.util
.stream
.Stream
;
19 public class MessageCache
{
21 private final static Logger logger
= LoggerFactory
.getLogger(MessageCache
.class);
23 private final File messageCachePath
;
25 public MessageCache(final File messageCachePath
) {
26 this.messageCachePath
= messageCachePath
;
29 public Iterable
<CachedMessage
> getCachedMessages() {
30 if (!messageCachePath
.exists()) {
31 return Collections
.emptyList();
34 return Arrays
.stream(Objects
.requireNonNull(messageCachePath
.listFiles())).flatMap(dir
-> {
36 return Stream
.of(dir
);
39 final var files
= Objects
.requireNonNull(dir
.listFiles());
40 if (files
.length
== 0) {
42 Files
.delete(dir
.toPath());
43 } catch (IOException e
) {
44 logger
.warn("Failed to delete cache dir “{}”, ignoring: {}", dir
, e
.getMessage());
46 return Stream
.empty();
48 return Arrays
.stream(files
).filter(File
::isFile
);
49 }).map(CachedMessage
::new).collect(Collectors
.toList());
52 public CachedMessage
cacheMessage(SignalServiceEnvelope envelope
, RecipientId recipientId
) {
53 final var now
= System
.currentTimeMillis();
56 var cacheFile
= getMessageCacheFile(recipientId
, now
, envelope
.getTimestamp());
57 MessageCacheUtils
.storeEnvelope(envelope
, cacheFile
);
58 return new CachedMessage(cacheFile
);
59 } catch (IOException e
) {
60 logger
.warn("Failed to store encrypted message in disk cache, ignoring: {}", e
.getMessage());
65 public CachedMessage
replaceSender(CachedMessage cachedMessage
, RecipientId sender
) throws IOException
{
66 final var cacheFile
= getMessageCacheFile(sender
, cachedMessage
.getFile().getName());
67 if (cacheFile
.equals(cachedMessage
.getFile())) {
70 Files
.move(cachedMessage
.getFile().toPath(), cacheFile
.toPath());
71 return new CachedMessage(cacheFile
);
74 public void deleteMessages(final RecipientId recipientId
) {
75 final var recipientMessageCachePath
= getMessageCachePath(recipientId
);
76 if (!recipientMessageCachePath
.exists()) {
80 for (var file
: Objects
.requireNonNull(recipientMessageCachePath
.listFiles())) {
86 Files
.delete(file
.toPath());
87 } catch (IOException e
) {
88 logger
.warn("Failed to delete cache file “{}”, ignoring: {}", file
, e
.getMessage());
93 private File
getMessageCachePath(RecipientId recipientId
) {
94 if (recipientId
== null) {
95 return messageCachePath
;
98 var sender
= String
.valueOf(recipientId
.id());
99 return new File(messageCachePath
, sender
.replace("/", "_"));
102 private File
getMessageCacheFile(RecipientId recipientId
, String filename
) throws IOException
{
103 var cachePath
= getMessageCachePath(recipientId
);
104 IOUtils
.createPrivateDirectories(cachePath
);
105 return new File(cachePath
, filename
);
108 private File
getMessageCacheFile(RecipientId recipientId
, long now
, long timestamp
) throws IOException
{
109 var cachePath
= getMessageCachePath(recipientId
);
110 IOUtils
.createPrivateDirectories(cachePath
);
111 return new File(cachePath
, now
+ "_" + timestamp
);
114 public void mergeRecipients(final RecipientId recipientId
, final RecipientId toBeMergedRecipientId
) {
115 final var toBeMergedMessageCachePath
= getMessageCachePath(toBeMergedRecipientId
);
116 if (!toBeMergedMessageCachePath
.exists()) {
120 for (var file
: Objects
.requireNonNull(toBeMergedMessageCachePath
.listFiles())) {
121 if (!file
.isFile()) {
126 final var cacheFile
= getMessageCacheFile(recipientId
, file
.getName());
127 Files
.move(file
.toPath(), cacheFile
.toPath());
128 } catch (IOException e
) {
129 logger
.warn("Failed to move cache file “{}”, ignoring: {}", file
, e
.getMessage());