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
.ServiceIdType
;
16 import org
.whispersystems
.signalservice
.api
.util
.UuidUtil
;
18 import java
.io
.InvalidObjectException
;
19 import java
.sql
.PreparedStatement
;
20 import java
.sql
.ResultSet
;
21 import java
.sql
.SQLException
;
22 import java
.util
.Optional
;
23 import java
.util
.Spliterator
;
24 import java
.util
.Spliterators
;
25 import java
.util
.function
.Consumer
;
26 import java
.util
.stream
.Stream
;
27 import java
.util
.stream
.StreamSupport
;
31 private static final Logger logger
= LoggerFactory
.getLogger(Utils
.class);
36 public static ObjectMapper
createStorageObjectMapper() {
37 final ObjectMapper objectMapper
= new ObjectMapper();
39 objectMapper
.setVisibility(PropertyAccessor
.ALL
, JsonAutoDetect
.Visibility
.PUBLIC_ONLY
);
40 objectMapper
.enable(SerializationFeature
.INDENT_OUTPUT
); // for pretty print
41 objectMapper
.disable(DeserializationFeature
.FAIL_ON_UNKNOWN_PROPERTIES
);
42 objectMapper
.disable(JsonParser
.Feature
.AUTO_CLOSE_SOURCE
);
43 objectMapper
.disable(JsonGenerator
.Feature
.AUTO_CLOSE_TARGET
);
48 public static JsonNode
getNotNullNode(JsonNode parent
, String name
) throws InvalidObjectException
{
49 var node
= parent
.get(name
);
50 if (node
== null || node
.isNull()) {
51 throw new InvalidObjectException(String
.format("Incorrect file format: expected parameter %s not found ",
58 public static RecipientAddress
getRecipientAddressFromIdentifier(final String identifier
) {
59 if (UuidUtil
.isUuid(identifier
)) {
60 return new RecipientAddress(UuidUtil
.parseOrThrow(identifier
));
62 return new RecipientAddress(Optional
.empty(), Optional
.of(identifier
));
66 public static int getAccountIdType(ServiceIdType serviceIdType
) {
67 return switch (serviceIdType
) {
73 public static <T
> T
executeQuerySingleRow(
74 PreparedStatement statement
, ResultSetMapper
<T
> mapper
75 ) throws SQLException
{
76 final var resultSet
= statement
.executeQuery();
77 if (!resultSet
.next()) {
78 throw new RuntimeException("Expected a row in result set, but none found.");
80 return mapper
.apply(resultSet
);
83 public static <T
> Optional
<T
> executeQueryForOptional(
84 PreparedStatement statement
, ResultSetMapper
<T
> mapper
85 ) throws SQLException
{
86 final var resultSet
= statement
.executeQuery();
87 if (!resultSet
.next()) {
88 return Optional
.empty();
90 return Optional
.ofNullable(mapper
.apply(resultSet
));
93 public static <T
> Stream
<T
> executeQueryForStream(
94 PreparedStatement statement
, ResultSetMapper
<T
> mapper
95 ) throws SQLException
{
96 final var resultSet
= statement
.executeQuery();
98 return StreamSupport
.stream(new Spliterators
.AbstractSpliterator
<>(Long
.MAX_VALUE
, Spliterator
.ORDERED
) {
100 public boolean tryAdvance(final Consumer
<?
super T
> consumer
) {
102 if (!resultSet
.next()) {
105 consumer
.accept(mapper
.apply(resultSet
));
107 } catch (SQLException e
) {
108 logger
.warn("Failed to read from database result", e
);
109 throw new RuntimeException(e
);
115 public interface ResultSetMapper
<T
> {
117 T
apply(ResultSet resultSet
) throws SQLException
;