1 package org
.asamk
.signal
.manager
.storage
;
3 import com
.fasterxml
.jackson
.annotation
.JsonAutoDetect
;
4 import com
.fasterxml
.jackson
.annotation
.PropertyAccessor
;
5 import com
.fasterxml
.jackson
.core
.JsonGenerator
;
6 import com
.fasterxml
.jackson
.core
.JsonParser
;
7 import com
.fasterxml
.jackson
.databind
.DeserializationFeature
;
8 import com
.fasterxml
.jackson
.databind
.JsonNode
;
9 import com
.fasterxml
.jackson
.databind
.ObjectMapper
;
10 import com
.fasterxml
.jackson
.databind
.SerializationFeature
;
12 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
13 import org
.slf4j
.Logger
;
14 import org
.slf4j
.LoggerFactory
;
15 import org
.whispersystems
.signalservice
.api
.push
.ServiceId
;
16 import org
.whispersystems
.signalservice
.api
.push
.ServiceIdType
;
17 import org
.whispersystems
.signalservice
.api
.util
.UuidUtil
;
19 import java
.io
.InvalidObjectException
;
20 import java
.sql
.PreparedStatement
;
21 import java
.sql
.ResultSet
;
22 import java
.sql
.SQLException
;
23 import java
.util
.Optional
;
24 import java
.util
.Spliterator
;
25 import java
.util
.Spliterators
;
26 import java
.util
.function
.Consumer
;
27 import java
.util
.stream
.Stream
;
28 import java
.util
.stream
.StreamSupport
;
32 private static final Logger logger
= LoggerFactory
.getLogger(Utils
.class);
37 public static ObjectMapper
createStorageObjectMapper() {
38 final ObjectMapper objectMapper
= new ObjectMapper();
40 objectMapper
.setVisibility(PropertyAccessor
.ALL
, JsonAutoDetect
.Visibility
.PUBLIC_ONLY
);
41 objectMapper
.enable(SerializationFeature
.INDENT_OUTPUT
); // for pretty print
42 objectMapper
.disable(DeserializationFeature
.FAIL_ON_UNKNOWN_PROPERTIES
);
43 objectMapper
.disable(JsonParser
.Feature
.AUTO_CLOSE_SOURCE
);
44 objectMapper
.disable(JsonGenerator
.Feature
.AUTO_CLOSE_TARGET
);
49 public static JsonNode
getNotNullNode(JsonNode parent
, String name
) throws InvalidObjectException
{
50 var node
= parent
.get(name
);
51 if (node
== null || node
.isNull()) {
52 throw new InvalidObjectException(String
.format("Incorrect file format: expected parameter %s not found ",
59 public static RecipientAddress
getRecipientAddressFromIdentifier(final String identifier
) {
60 if (UuidUtil
.isUuid(identifier
)) {
61 return new RecipientAddress(ServiceId
.parseOrThrow(identifier
));
63 return new RecipientAddress(Optional
.empty(), Optional
.of(identifier
));
67 public static int getAccountIdType(ServiceIdType serviceIdType
) {
68 return switch (serviceIdType
) {
74 public static <T
> T
executeQuerySingleRow(
75 PreparedStatement statement
, ResultSetMapper
<T
> mapper
76 ) throws SQLException
{
77 final var resultSet
= statement
.executeQuery();
78 if (!resultSet
.next()) {
79 throw new RuntimeException("Expected a row in result set, but none found.");
81 return mapper
.apply(resultSet
);
84 public static <T
> Optional
<T
> executeQueryForOptional(
85 PreparedStatement statement
, ResultSetMapper
<T
> mapper
86 ) throws SQLException
{
87 final var resultSet
= statement
.executeQuery();
88 if (!resultSet
.next()) {
89 return Optional
.empty();
91 return Optional
.ofNullable(mapper
.apply(resultSet
));
94 public static <T
> Stream
<T
> executeQueryForStream(
95 PreparedStatement statement
, ResultSetMapper
<T
> mapper
96 ) throws SQLException
{
97 final var resultSet
= statement
.executeQuery();
99 return StreamSupport
.stream(new Spliterators
.AbstractSpliterator
<>(Long
.MAX_VALUE
, Spliterator
.ORDERED
) {
101 public boolean tryAdvance(final Consumer
<?
super T
> consumer
) {
103 if (!resultSet
.next()) {
106 consumer
.accept(mapper
.apply(resultSet
));
108 } catch (SQLException e
) {
109 logger
.warn("Failed to read from database result", e
);
110 throw new RuntimeException(e
);
116 public interface ResultSetMapper
<T
> {
118 T
apply(ResultSet resultSet
) throws SQLException
;