Search in sources :

Example 1 with ProtobufDifference

use of io.apicurio.registry.protobuf.ProtobufDifference in project apicurio-registry by Apicurio.

the class ProtobufKafkaSerializer method serializeData.

/**
 * @see io.apicurio.registry.serde.AbstractKafkaSerializer#serializeData(org.apache.kafka.common.header.Headers, io.apicurio.registry.serde.ParsedSchema, java.lang.Object, java.io.OutputStream)
 */
@Override
protected void serializeData(Headers headers, ParsedSchema<ProtobufSchema> schema, U data, OutputStream out) throws IOException {
    if (validationEnabled) {
        if (schema.getParsedSchema() != null && schema.getParsedSchema().getFileDescriptor().findMessageTypeByName(data.getDescriptorForType().getName()) == null) {
            throw new SerializationException("Missing message type " + data.getDescriptorForType().getName() + " in the protobuf schema");
        }
        List<ProtobufDifference> diffs = validate(schema, data);
        if (!diffs.isEmpty()) {
            throw new SerializationException("The data to send is not compatible with the schema. " + diffs);
        }
    }
    if (headers != null) {
        serdeHeaders.addMessageTypeHeader(headers, data.getClass().getName());
        serdeHeaders.addProtobufTypeNameHeader(headers, data.getDescriptorForType().getName());
    } else {
        Ref ref = Ref.newBuilder().setName(data.getDescriptorForType().getName()).build();
        ref.writeDelimitedTo(out);
    }
    data.writeTo(out);
}
Also used : Ref(io.apicurio.registry.serde.protobuf.ref.RefOuterClass.Ref) SerializationException(org.apache.kafka.common.errors.SerializationException) ProtobufDifference(io.apicurio.registry.protobuf.ProtobufDifference)

Example 2 with ProtobufDifference

use of io.apicurio.registry.protobuf.ProtobufDifference in project apicurio-registry by Apicurio.

the class ProtobufCompatibilityCheckerLibrary method checkNoChangingFieldTypes.

/**
 * Determine if any field type has been changed.
 *
 * @return differences list
 */
public List<ProtobufDifference> checkNoChangingFieldTypes() {
    List<ProtobufDifference> issues = new ArrayList<>();
    Map<String, Map<String, FieldElement>> before = fileBefore.getFieldMap();
    Map<String, Map<String, FieldElement>> after = fileAfter.getFieldMap();
    for (Map.Entry<String, Map<String, FieldElement>> entry : before.entrySet()) {
        Map<String, FieldElement> afterMap = after.get(entry.getKey());
        if (afterMap != null) {
            for (Map.Entry<String, FieldElement> beforeKV : entry.getValue().entrySet()) {
                FieldElement afterFE = afterMap.get(beforeKV.getKey());
                if (afterFE != null) {
                    String beforeType = normalizeType(fileBefore, beforeKV.getValue().getType());
                    String afterType = normalizeType(fileAfter, afterFE.getType());
                    if (afterFE != null && !beforeType.equals(afterType)) {
                        issues.add(ProtobufDifference.from(String.format("Field type changed, message %s , before: %s , after %s", entry.getKey(), beforeKV.getValue().getType(), afterFE.getType())));
                    }
                    if (afterFE != null && !Objects.equals(beforeKV.getValue().getLabel(), afterFE.getLabel())) {
                        issues.add(ProtobufDifference.from(String.format("Field label changed, message %s , before: %s , after %s", entry.getKey(), beforeKV.getValue().getLabel(), afterFE.getLabel())));
                    }
                }
            }
        }
    }
    return issues;
}
Also used : ProtobufDifference(io.apicurio.registry.protobuf.ProtobufDifference) ArrayList(java.util.ArrayList) FieldElement(com.squareup.wire.schema.internal.parser.FieldElement) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with ProtobufDifference

use of io.apicurio.registry.protobuf.ProtobufDifference in project apicurio-registry by Apicurio.

the class ProtobufCompatibilityCheckerLibrary method checkNoChangingFieldIDs.

/**
 * Determine if any field ID number has been changed.
 *
 * @return differences list
 */
public List<ProtobufDifference> checkNoChangingFieldIDs() {
    List<ProtobufDifference> issues = new ArrayList<>();
    Map<String, Map<String, FieldElement>> before = fileBefore.getFieldMap();
    Map<String, Map<String, FieldElement>> after = fileAfter.getFieldMap();
    for (Map.Entry<String, Map<String, FieldElement>> entry : before.entrySet()) {
        Map<String, FieldElement> afterMap = after.get(entry.getKey());
        if (afterMap != null) {
            for (Map.Entry<String, FieldElement> beforeKV : entry.getValue().entrySet()) {
                FieldElement afterFE = afterMap.get(beforeKV.getKey());
                if (afterFE != null && beforeKV.getValue().getTag() != afterFE.getTag()) {
                    issues.add(ProtobufDifference.from(String.format("Conflict, field id changed, message %s , before: %s , after %s", entry.getKey(), beforeKV.getValue().getTag(), afterFE.getTag())));
                }
            }
        }
    }
    Map<String, Map<String, EnumConstantElement>> beforeEnum = fileBefore.getEnumFieldMap();
    Map<String, Map<String, EnumConstantElement>> afterEnum = fileAfter.getEnumFieldMap();
    for (Map.Entry<String, Map<String, EnumConstantElement>> entry : beforeEnum.entrySet()) {
        Map<String, EnumConstantElement> afterMap = afterEnum.get(entry.getKey());
        if (afterMap != null) {
            for (Map.Entry<String, EnumConstantElement> beforeKV : entry.getValue().entrySet()) {
                EnumConstantElement afterECE = afterMap.get(beforeKV.getKey());
                if (afterECE != null && beforeKV.getValue().getTag() != afterECE.getTag()) {
                    issues.add(ProtobufDifference.from(String.format("Conflict, field id changed, message %s , before: %s , after %s", entry.getKey(), beforeKV.getValue().getTag(), afterECE.getTag())));
                }
            }
        }
    }
    return issues;
}
Also used : ProtobufDifference(io.apicurio.registry.protobuf.ProtobufDifference) ArrayList(java.util.ArrayList) FieldElement(com.squareup.wire.schema.internal.parser.FieldElement) EnumConstantElement(com.squareup.wire.schema.internal.parser.EnumConstantElement) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with ProtobufDifference

use of io.apicurio.registry.protobuf.ProtobufDifference in project apicurio-registry by Apicurio.

the class ProtobufCompatibilityCheckerLibrary method checkNoRemovingFieldsWithoutReserve.

/**
 * Determine if any field has been removed without a corresponding reservation of that field name or ID.
 * <p>
 * Note: TODO can't currently validate enum reserved fields, as the parser doesn't capture those.
 *
 * @return differences list
 */
public List<ProtobufDifference> checkNoRemovingFieldsWithoutReserve() {
    List<ProtobufDifference> issues = new ArrayList<>();
    Map<String, Map<String, FieldElement>> before = fileBefore.getFieldMap();
    Map<String, Map<String, FieldElement>> after = fileAfter.getFieldMap();
    Map<String, Set<Object>> afterReservedFields = fileAfter.getReservedFields();
    Map<String, Set<Object>> afterNonreservedFields = fileAfter.getNonReservedFields();
    for (Map.Entry<String, Map<String, FieldElement>> entry : before.entrySet()) {
        Set<String> removedFieldNames = new HashSet<>(entry.getValue().keySet());
        Map<String, FieldElement> updated = after.get(entry.getKey());
        if (updated != null) {
            removedFieldNames.removeAll(updated.keySet());
        }
        int issuesCount = 0;
        // count once for each non-reserved field name
        Set<Object> reserved = afterReservedFields.getOrDefault(entry.getKey(), Collections.emptySet());
        Set<Object> nonreserved = afterNonreservedFields.getOrDefault(entry.getKey(), Collections.emptySet());
        Set<String> nonReservedRemovedFieldNames = new HashSet<>(removedFieldNames);
        nonReservedRemovedFieldNames.removeAll(reserved);
        issuesCount += nonReservedRemovedFieldNames.size();
        // count again for each non-reserved field id
        for (FieldElement fieldElement : entry.getValue().values()) {
            if (removedFieldNames.contains(fieldElement.getName()) && !(reserved.contains(fieldElement.getTag()) || nonreserved.contains(fieldElement.getTag()))) {
                issuesCount++;
            }
        }
        if (issuesCount > 0) {
            issues.add(ProtobufDifference.from(String.format("%d fields removed without reservation, message %s", issuesCount, entry.getKey())));
        }
    }
    return issues;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ProtobufDifference(io.apicurio.registry.protobuf.ProtobufDifference) ArrayList(java.util.ArrayList) FieldElement(com.squareup.wire.schema.internal.parser.FieldElement) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 5 with ProtobufDifference

use of io.apicurio.registry.protobuf.ProtobufDifference in project apicurio-registry by Apicurio.

the class ProtobufCompatibilityCheckerLibrary method checkRequiredFields.

/**
 * Determine if any required field has been added in the new version.
 *
 * @return differences list
 */
public List<ProtobufDifference> checkRequiredFields() {
    List<ProtobufDifference> issues = new ArrayList<>();
    Map<String, Map<String, FieldElement>> before = fileBefore.getFieldMap();
    Map<String, Map<String, FieldElement>> after = fileAfter.getFieldMap();
    for (Map.Entry<String, Map<String, FieldElement>> entry : after.entrySet()) {
        Map<String, FieldElement> beforeMap = before.get(entry.getKey());
        if (beforeMap != null) {
            for (Map.Entry<String, FieldElement> afterKV : entry.getValue().entrySet()) {
                FieldElement afterSig = beforeMap.get(afterKV.getKey());
                if (afterSig == null && afterKV.getValue().getLabel() != null && afterKV.getValue().getLabel().equals(Field.Label.REQUIRED)) {
                    issues.add(ProtobufDifference.from(String.format("required field added in new version, message %s, after %s", entry.getKey(), afterKV.getValue())));
                }
            }
        }
    }
    return issues;
}
Also used : ProtobufDifference(io.apicurio.registry.protobuf.ProtobufDifference) ArrayList(java.util.ArrayList) FieldElement(com.squareup.wire.schema.internal.parser.FieldElement) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ProtobufDifference (io.apicurio.registry.protobuf.ProtobufDifference)5 FieldElement (com.squareup.wire.schema.internal.parser.FieldElement)4 ArrayList (java.util.ArrayList)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 EnumConstantElement (com.squareup.wire.schema.internal.parser.EnumConstantElement)1 Ref (io.apicurio.registry.serde.protobuf.ref.RefOuterClass.Ref)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 SerializationException (org.apache.kafka.common.errors.SerializationException)1