|
@@ -1,6 +1,7 @@
|
|
package com.provectus.kafka.ui.serde;
|
|
package com.provectus.kafka.ui.serde;
|
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
+import com.google.protobuf.Descriptors.Descriptor;
|
|
import com.google.protobuf.DynamicMessage;
|
|
import com.google.protobuf.DynamicMessage;
|
|
import com.google.protobuf.util.JsonFormat;
|
|
import com.google.protobuf.util.JsonFormat;
|
|
import com.provectus.kafka.ui.model.MessageSchema;
|
|
import com.provectus.kafka.ui.model.MessageSchema;
|
|
@@ -14,6 +15,8 @@ import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Path;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.Optional;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
@@ -30,15 +33,35 @@ public class ProtobufFileRecordSerDe implements RecordSerDe {
|
|
private final ObjectMapper objectMapper;
|
|
private final ObjectMapper objectMapper;
|
|
private final Path protobufSchemaPath;
|
|
private final Path protobufSchemaPath;
|
|
private final ProtobufSchemaConverter schemaConverter = new ProtobufSchemaConverter();
|
|
private final ProtobufSchemaConverter schemaConverter = new ProtobufSchemaConverter();
|
|
|
|
+ private final Map<String, Descriptor> messageDescriptorMap;
|
|
|
|
+ private final Descriptor defaultMessageDescriptor;
|
|
|
|
|
|
- public ProtobufFileRecordSerDe(Path protobufSchemaPath, String messageName,
|
|
|
|
- ObjectMapper objectMapper) throws IOException {
|
|
|
|
|
|
+ public ProtobufFileRecordSerDe(Path protobufSchemaPath, Map<String, String> messageNameMap,
|
|
|
|
+ String defaultMessageName, ObjectMapper objectMapper)
|
|
|
|
+ throws IOException {
|
|
this.objectMapper = objectMapper;
|
|
this.objectMapper = objectMapper;
|
|
this.protobufSchemaPath = protobufSchemaPath;
|
|
this.protobufSchemaPath = protobufSchemaPath;
|
|
try (final Stream<String> lines = Files.lines(protobufSchemaPath)) {
|
|
try (final Stream<String> lines = Files.lines(protobufSchemaPath)) {
|
|
- this.protobufSchema = new ProtobufSchema(
|
|
|
|
|
|
+ var schema = new ProtobufSchema(
|
|
lines.collect(Collectors.joining("\n"))
|
|
lines.collect(Collectors.joining("\n"))
|
|
- ).copy(messageName);
|
|
|
|
|
|
+ );
|
|
|
|
+ if (defaultMessageName != null) {
|
|
|
|
+ this.protobufSchema = schema.copy(defaultMessageName);
|
|
|
|
+ } else {
|
|
|
|
+ this.protobufSchema = schema;
|
|
|
|
+ }
|
|
|
|
+ this.messageDescriptorMap = new HashMap<>();
|
|
|
|
+ if (messageNameMap != null) {
|
|
|
|
+ for (Map.Entry<String, String> entry : messageNameMap.entrySet()) {
|
|
|
|
+ var descriptor = Objects.requireNonNull(protobufSchema.toDescriptor(entry.getValue()),
|
|
|
|
+ "The given message type is not found in protobuf definition: "
|
|
|
|
+ + entry.getValue());
|
|
|
|
+ messageDescriptorMap.put(entry.getKey(), descriptor);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ defaultMessageDescriptor = Objects.requireNonNull(protobufSchema.toDescriptor(),
|
|
|
|
+ "The given message type is not found in protobuf definition: "
|
|
|
|
+ + defaultMessageName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -51,7 +74,7 @@ public class ProtobufFileRecordSerDe implements RecordSerDe {
|
|
builder.keyFormat(MessageFormat.UNKNOWN);
|
|
builder.keyFormat(MessageFormat.UNKNOWN);
|
|
}
|
|
}
|
|
if (msg.value() != null) {
|
|
if (msg.value() != null) {
|
|
- builder.value(parse(msg.value().get()));
|
|
|
|
|
|
+ builder.value(parse(msg.value().get(), getDescriptor(msg.topic())));
|
|
builder.valueFormat(MessageFormat.PROTOBUF);
|
|
builder.valueFormat(MessageFormat.PROTOBUF);
|
|
}
|
|
}
|
|
return builder.build();
|
|
return builder.build();
|
|
@@ -60,11 +83,15 @@ public class ProtobufFileRecordSerDe implements RecordSerDe {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private Descriptor getDescriptor(String topic) {
|
|
|
|
+ return messageDescriptorMap.getOrDefault(topic, defaultMessageDescriptor);
|
|
|
|
+ }
|
|
|
|
+
|
|
@SneakyThrows
|
|
@SneakyThrows
|
|
- private String parse(byte[] value) {
|
|
|
|
|
|
+ private String parse(byte[] value, Descriptor descriptor) {
|
|
DynamicMessage protoMsg = DynamicMessage.parseFrom(
|
|
DynamicMessage protoMsg = DynamicMessage.parseFrom(
|
|
- protobufSchema.toDescriptor(),
|
|
|
|
- new ByteArrayInputStream(value)
|
|
|
|
|
|
+ descriptor,
|
|
|
|
+ new ByteArrayInputStream(value)
|
|
);
|
|
);
|
|
byte[] jsonFromProto = ProtobufSchemaUtils.toJson(protoMsg);
|
|
byte[] jsonFromProto = ProtobufSchemaUtils.toJson(protoMsg);
|
|
return new String(jsonFromProto);
|
|
return new String(jsonFromProto);
|
|
@@ -78,7 +105,7 @@ public class ProtobufFileRecordSerDe implements RecordSerDe {
|
|
if (data == null) {
|
|
if (data == null) {
|
|
return new ProducerRecord<>(topic, partition, Objects.requireNonNull(key).getBytes(), null);
|
|
return new ProducerRecord<>(topic, partition, Objects.requireNonNull(key).getBytes(), null);
|
|
}
|
|
}
|
|
- DynamicMessage.Builder builder = protobufSchema.newMessageBuilder();
|
|
|
|
|
|
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(getDescriptor(topic));
|
|
try {
|
|
try {
|
|
JsonFormat.parser().merge(data, builder);
|
|
JsonFormat.parser().merge(data, builder);
|
|
final DynamicMessage message = builder.build();
|
|
final DynamicMessage message = builder.build();
|
|
@@ -97,8 +124,8 @@ public class ProtobufFileRecordSerDe implements RecordSerDe {
|
|
public TopicMessageSchema getTopicSchema(String topic) {
|
|
public TopicMessageSchema getTopicSchema(String topic) {
|
|
|
|
|
|
final JsonSchema jsonSchema = schemaConverter.convert(
|
|
final JsonSchema jsonSchema = schemaConverter.convert(
|
|
- protobufSchemaPath.toUri(),
|
|
|
|
- protobufSchema.toDescriptor()
|
|
|
|
|
|
+ protobufSchemaPath.toUri(),
|
|
|
|
+ getDescriptor(topic)
|
|
);
|
|
);
|
|
final MessageSchema keySchema = new MessageSchema()
|
|
final MessageSchema keySchema = new MessageSchema()
|
|
.name(protobufSchema.fullName())
|
|
.name(protobufSchema.fullName())
|