├── NOTICE ├── checkstyle ├── example.importorder ├── import-control-core.xml ├── suppressions.xml ├── intelij.xml ├── import-control.xml └── spotbugs-include.xml ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── jacoco.gradle ├── eclipse.gradle ├── spotbugs.gradle ├── idea.gradle ├── checkstyle.gradle ├── rat.gradle ├── application.gradle └── protobuf.gradle ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── server └── src │ ├── test │ ├── resources │ │ ├── proto │ │ │ ├── protobufTest.pb │ │ │ └── protobufTest.proto │ │ └── logback.xml │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ ├── pravegastandalone │ │ └── PravegaStandaloneUtils.java │ │ └── server │ │ └── rest │ │ ├── ConfigTest.java │ │ └── auth │ │ └── AuthHandlerManagerTest.java │ ├── main │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ ├── storage │ │ ├── StoreType.java │ │ ├── client │ │ │ ├── VersionedRecord.java │ │ │ ├── VersionedEntry.java │ │ │ └── Version.java │ │ ├── RetryableException.java │ │ ├── Etag.java │ │ ├── ContinuationToken.java │ │ ├── SchemaStoreFactory.java │ │ └── impl │ │ │ ├── group │ │ │ ├── records │ │ │ │ ├── EncodingIdSerializer.java │ │ │ │ ├── VersionInfoSerializer.java │ │ │ │ ├── CompatibilitySerializer.java │ │ │ │ └── NamespaceAndGroup.java │ │ │ └── GroupTable.java │ │ │ └── groups │ │ │ └── GroupsValue.java │ │ ├── exceptions │ │ ├── RegistryServiceException.java │ │ ├── ResourceNotFoundException.java │ │ ├── CodecTypeNotRegisteredException.java │ │ ├── PreconditionFailedException.java │ │ ├── IncompatibleSchemaException.java │ │ └── SerializationFormatMismatchException.java │ │ ├── ResultPage.java │ │ ├── server │ │ └── rest │ │ │ ├── resources │ │ │ ├── PingImpl.java │ │ │ └── AuthResources.java │ │ │ ├── RegistryApplication.java │ │ │ └── CustomJsonParser.java │ │ └── rules │ │ ├── AlwaysTrueCompatibilityChecker.java │ │ ├── CompatibilityCheckerFactory.java │ │ └── CompatibilityChecker.java │ └── conf │ ├── logback.xml │ └── schema-registry.config.properties ├── test └── src │ ├── test │ ├── resources │ │ └── proto │ │ │ └── protobufTest.pb │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── integrationtest │ │ ├── TestInMemoryEndToEnd.java │ │ ├── TestPravegaEndToEnd.java │ │ └── TestEndToEndWithFailingAuth.java │ └── main │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── integrationtest │ ├── Address.java │ ├── User.java │ ├── DerivedUser1.java │ └── DerivedUser2.java ├── serializers ├── src │ ├── test │ │ └── resources │ │ │ ├── proto │ │ │ ├── protobufTest.pb │ │ │ └── protobufTest.proto │ │ │ └── avro │ │ │ ├── avroTest1.avsc │ │ │ ├── avroTest2.avsc │ │ │ └── avroTest3.avsc │ └── main │ │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── serializers │ │ ├── MultipleFormatSerializer.java │ │ ├── JsonWithSchemaDeserializer.java │ │ ├── MultipleFormatDeserializer.java │ │ └── MultiFormatWithSchemaDeserializer.java ├── protobuf │ └── src │ │ ├── test │ │ └── resources │ │ │ └── proto │ │ │ ├── protobufTest.pb │ │ │ └── protobufTest.proto │ │ └── main │ │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── serializer │ │ └── protobuf │ │ └── impl │ │ ├── ProtobufSerializer.java │ │ └── ProtobufDeserializer.java ├── avro │ └── src │ │ ├── test │ │ ├── resources │ │ │ └── avro │ │ │ │ ├── avroTest1.avsc │ │ │ │ ├── avroTest2.avsc │ │ │ │ ├── avroTest3.avsc │ │ │ │ └── user.avsc │ │ └── java │ │ │ └── io │ │ │ └── pravega │ │ │ └── schemaregistry │ │ │ └── serializer │ │ │ └── avro │ │ │ ├── testobjs │ │ │ ├── EventTimestampAware.java │ │ │ └── SchemaDefinitions.java │ │ │ └── schemas │ │ │ └── SchemasTest.java │ │ └── main │ │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── serializer │ │ └── avro │ │ └── impl │ │ └── AvroSerializer.java ├── shared │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── pravega │ │ │ └── schemaregistry │ │ │ └── serializer │ │ │ └── shared │ │ │ ├── impl │ │ │ ├── CustomSerializer.java │ │ │ ├── CustomDeserializer.java │ │ │ ├── BaseDeserializer.java │ │ │ ├── BaseSerializer.java │ │ │ ├── MultiplexedSerializer.java │ │ │ ├── MultiplexedDeserializer.java │ │ │ ├── MultiplexedAndGenericDeserializer.java │ │ │ └── EncodingCache.java │ │ │ ├── schemas │ │ │ └── Schema.java │ │ │ ├── codec │ │ │ ├── Decoder.java │ │ │ ├── Codec.java │ │ │ └── Encoder.java │ │ │ └── credentials │ │ │ └── PravegaCredentialProvider.java │ │ └── test │ │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── serializer │ │ └── shared │ │ └── testobjs │ │ ├── Address.java │ │ ├── User.java │ │ ├── DerivedUser1.java │ │ └── DerivedUser2.java └── json │ └── src │ ├── main │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── serializer │ │ └── json │ │ └── impl │ │ ├── JsonSerializer.java │ │ ├── JsonGenericDeserializer.java │ │ ├── JsonStringDeserializer.java │ │ └── JsonDeserializer.java │ └── test │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── serializer │ └── json │ ├── schemas │ └── SchemasTest.java │ └── testobjs │ └── SchemaDefinitions.java ├── HEADER ├── .gitignore ├── contract └── src │ └── main │ ├── swagger │ ├── server.config.json │ └── README.md │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── contract │ ├── data │ ├── SchemaWithVersion.java │ ├── EncodingInfo.java │ ├── EncodingId.java │ ├── GroupHistoryRecord.java │ ├── CodecType.java │ ├── VersionInfo.java │ └── SerializationFormat.java │ └── generated │ └── rest │ └── model │ ├── Forward.java │ ├── Backward.java │ ├── Valid.java │ ├── ForwardTransitive.java │ ├── BackwardTransitive.java │ ├── EncodingId.java │ └── ForwardPolicy.java ├── documentation └── src │ ├── docs │ ├── security.md │ ├── contributing.md │ └── installation-guide.md │ └── mkdocs.yml ├── docker └── pravega-schema-registry │ ├── scripts │ ├── init_schemaregistry.sh │ ├── common.sh │ ├── entrypoint.sh │ └── wait_for │ └── Dockerfile ├── charts └── schema-registry │ ├── Chart.yaml │ └── templates │ ├── service_account.yaml │ ├── service.yaml │ ├── ingress.yaml │ ├── _helpers.tpl │ └── configmap.yaml ├── settings.gradle ├── common └── src │ ├── main │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── common │ │ ├── HashUtil.java │ │ └── Either.java │ └── test │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── common │ ├── ContinuationTokenIteratorTest.java │ ├── ChunkUtilTest.java │ └── FuturesUtilityTest.java ├── client └── src │ ├── test │ └── java │ │ └── io │ │ └── pravega │ │ └── schemaregistry │ │ └── client │ │ ├── SchemaRegistryClientTest.java │ │ └── SchemaRegistryClientConfigTest.java │ └── main │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── client │ ├── AuthFilter.java │ └── SchemaRegistryClientFactory.java ├── auth └── src │ └── main │ └── java │ └── io │ └── pravega │ └── schemaregistry │ └── common │ ├── CredentialProvider.java │ └── AuthHelper.java └── gradle.properties /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /checkstyle/example.importorder: -------------------------------------------------------------------------------- 1 | #Organize Import Order 2 | #Wed Feb 12 14:13:16 PDT 2020 3 | 1=\# 4 | 0= 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pravega/schema-registry/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Problem description** 2 | 3 | 4 | **Problem location** 5 | 6 | 7 | **Suggestions for an improvement** 8 | -------------------------------------------------------------------------------- /server/src/test/resources/proto/protobufTest.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pravega/schema-registry/HEAD/server/src/test/resources/proto/protobufTest.pb -------------------------------------------------------------------------------- /test/src/test/resources/proto/protobufTest.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pravega/schema-registry/HEAD/test/src/test/resources/proto/protobufTest.pb -------------------------------------------------------------------------------- /serializers/src/test/resources/proto/protobufTest.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pravega/schema-registry/HEAD/serializers/src/test/resources/proto/protobufTest.pb -------------------------------------------------------------------------------- /serializers/protobuf/src/test/resources/proto/protobufTest.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pravega/schema-registry/HEAD/serializers/protobuf/src/test/resources/proto/protobufTest.pb -------------------------------------------------------------------------------- /serializers/src/test/resources/avro/avroTest1.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type1", 5 | "fields": [ 6 | {"name": "a", "type": "string"}, 7 | {"name": "b", "type": "int"} 8 | ] 9 | } -------------------------------------------------------------------------------- /serializers/avro/src/test/resources/avro/avroTest1.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type1", 5 | "fields": [ 6 | {"name": "a", "type": "string"}, 7 | {"name": "b", "type": "int"} 8 | ] 9 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Feb 10 03:52:31 PST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip 7 | -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.iws 3 | *.ipr 4 | *.log.gz 5 | *.tmp 6 | /out 7 | .project 8 | build 9 | .classpath 10 | .DS_Store 11 | bin/ 12 | classes/ 13 | .settings 14 | .gradle 15 | output 16 | .idea 17 | target 18 | log/ 19 | out/ 20 | .metadata/ 21 | .recommenders/ 22 | *.log 23 | .nb-gradle 24 | .nb-gradle-properties 25 | -------------------------------------------------------------------------------- /serializers/src/test/resources/avro/avroTest2.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type2", 5 | "fields": [ 6 | {"name": "c", "type": "string"}, 7 | {"name": "d", "type": "int"}, 8 | {"name": "e", "type": "string"} 9 | ] 10 | } -------------------------------------------------------------------------------- /serializers/avro/src/test/resources/avro/avroTest2.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type2", 5 | "fields": [ 6 | {"name": "c", "type": "string"}, 7 | {"name": "d", "type": "int"}, 8 | {"name": "e", "type": "string"} 9 | ] 10 | } -------------------------------------------------------------------------------- /contract/src/main/swagger/server.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceFolder" : "src/main/java", 3 | "implFolder" : "src/main/java", 4 | "modelPackage" : "io.pravega.schemaregistry.contract.generated.rest.model", 5 | "apiPackage" : "io.pravega.schemaregistry.contract.generated.rest.server.api", 6 | "library" : "jersey2", 7 | "hideGenerationTimestamp" : true 8 | } 9 | -------------------------------------------------------------------------------- /serializers/src/test/resources/avro/avroTest3.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type3", 5 | "fields": [ 6 | {"name": "f", "type": "string"}, 7 | {"name": "g", "type": "int"}, 8 | {"name": "h", "type": "string"}, 9 | {"name": "i", "type": "string"} 10 | ] 11 | } -------------------------------------------------------------------------------- /serializers/avro/src/test/resources/avro/avroTest3.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "io.pravega.schemaregistry.testobjs.generated", 3 | "type": "record", 4 | "name": "Type3", 5 | "fields": [ 6 | {"name": "f", "type": "string"}, 7 | {"name": "g", "type": "int"}, 8 | {"name": "h", "type": "string"}, 9 | {"name": "i", "type": "string"} 10 | ] 11 | } -------------------------------------------------------------------------------- /documentation/src/docs/security.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | Coming Soon! 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Change log description** 2 | (2-3 concise points about the changes in this PR. When committing this PR, the committer is expected to copy the content of this section to the merge description box) 3 | 4 | **Purpose of the change** 5 | (_e.g._, Fixes #666, Closes #1234) 6 | 7 | **What the code does** 8 | (Detailed description of the code changes) 9 | 10 | **How to verify it** 11 | (Optional: steps to verify that the changes are effective) 12 | -------------------------------------------------------------------------------- /docker/pravega-schema-registry/scripts/init_schemaregistry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | 12 | init_schemaregistry() { 13 | add_system_property "schema-registry.store.pravega.controller.connect.uri" "${CONTROLLER_URL}" 14 | echo "JAVA_OPTS=${JAVA_OPTS}" 15 | } 16 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/StoreType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage; 11 | 12 | /** 13 | * {@link SchemaStore} Type. 14 | */ 15 | public enum StoreType { 16 | InMemory, 17 | Pravega 18 | } 19 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Pravega Schema Registry 2 | ============================================ 3 | 4 | Pravega community follows specific rules and principles. If you're already familiar with them, you'll feel right at home. 5 | 6 | Otherwise, please go read Pravega's 7 | * [Contributions guidelines](https://github.com/pravega/pravega/wiki/Contributing) 8 | * [Issue triaging and labeling](https://github.com/pravega/pravega/wiki/Issues-Triaging-and-Labeling) 9 | * [Review process](https://github.com/pravega/pravega/wiki/Pull-Request-and-Reviews) 10 | 11 | Happy hacking! 12 | -------------------------------------------------------------------------------- /charts/schema-registry/Chart.yaml: -------------------------------------------------------------------------------- 1 | # /** 2 | # * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # * 4 | # * Licensed under the Apache License, Version 2.0 (the "License"); 5 | # * you may not use this file except in compliance with the License. 6 | # * You may obtain a copy of the License at 7 | # * 8 | # * http://www.apache.org/licenses/LICENSE-2.0 9 | # */ 10 | 11 | apiVersion: v2 12 | name: schema-registry 13 | description: Schema Registry Helm chart for Kubernetes 14 | type: application 15 | version: 0.5.0 16 | appVersion: 0.5.0 17 | home: https://github.com/pravega/schema-registry 18 | -------------------------------------------------------------------------------- /server/src/test/resources/proto/protobufTest.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package io.pravega.schemaregistry.testobjs.generated; 3 | 4 | message InternalMessage { 5 | enum Values { 6 | val1 = 0; 7 | val2 = 1; 8 | val3 = 2; 9 | val4 = 3; 10 | } 11 | Values value = 1; 12 | } 13 | 14 | message Message1 { 15 | InternalMessage internal = 1; 16 | string name = 2; 17 | } 18 | 19 | message Message2 { 20 | string name = 1; 21 | int32 field1 = 2; 22 | } 23 | 24 | message Message3 { 25 | string name = 1; 26 | int32 field1 = 2; 27 | int32 field2 = 3; 28 | } 29 | -------------------------------------------------------------------------------- /serializers/src/test/resources/proto/protobufTest.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package io.pravega.schemaregistry.testobjs.generated; 3 | 4 | message InternalMessage { 5 | enum Values { 6 | val1 = 0; 7 | val2 = 1; 8 | val3 = 2; 9 | val4 = 3; 10 | } 11 | Values value = 1; 12 | } 13 | 14 | message Message1 { 15 | InternalMessage internal = 1; 16 | string name = 2; 17 | } 18 | 19 | message Message2 { 20 | string name = 1; 21 | int32 field1 = 2; 22 | } 23 | 24 | message Message3 { 25 | string name = 1; 26 | int32 field1 = 2; 27 | int32 field2 = 3; 28 | } 29 | -------------------------------------------------------------------------------- /serializers/protobuf/src/test/resources/proto/protobufTest.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package io.pravega.schemaregistry.testobjs.generated; 3 | 4 | message InternalMessage { 5 | enum Values { 6 | val1 = 0; 7 | val2 = 1; 8 | val3 = 2; 9 | val4 = 3; 10 | } 11 | Values value = 1; 12 | } 13 | 14 | message Message1 { 15 | InternalMessage internal = 1; 16 | string name = 2; 17 | } 18 | 19 | message Message2 { 20 | string name = 1; 21 | int32 field1 = 2; 22 | } 23 | 24 | message Message3 { 25 | string name = 1; 26 | int32 field1 = 2; 27 | int32 field2 = 3; 28 | } 29 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/client/VersionedRecord.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.client; 11 | 12 | import lombok.Data; 13 | 14 | @Data 15 | public class VersionedRecord { 16 | private final T record; 17 | private final Version version; 18 | } 19 | -------------------------------------------------------------------------------- /serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/EventTimestampAware.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.avro.testobjs; 11 | 12 | public interface EventTimestampAware { 13 | void setEventTimestamp(Long value); 14 | 15 | Long getEventTimestamp(); 16 | } 17 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/client/VersionedEntry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.client; 11 | 12 | import lombok.Data; 13 | 14 | @Data 15 | public class VersionedEntry { 16 | private final K key; 17 | private final VersionedRecord value; 18 | } 19 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/RetryableException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage; 11 | 12 | /** 13 | * Retryable trait on exceptions. This trait can be used to determine if the exception should be retried or not. 14 | */ 15 | public interface RetryableException { 16 | } 17 | -------------------------------------------------------------------------------- /docker/pravega-schema-registry/scripts/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | 12 | # Adds a system property if the value is not empty 13 | add_system_property() { 14 | local name=$1 15 | local value=$2 16 | 17 | if [ -n "${value}" ]; then 18 | export JAVA_OPTS="${JAVA_OPTS} -D${name}=${value}" 19 | fi 20 | } 21 | 22 | -------------------------------------------------------------------------------- /gradle/jacoco.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | plugins.withId('jacoco') { 12 | jacoco { 13 | toolVersion = jacocoVersion 14 | } 15 | jacocoTestReport { 16 | reports { 17 | xml.enabled true 18 | html.enabled false 19 | } 20 | } 21 | 22 | test { finalizedBy jacocoTestReport } 23 | } 24 | -------------------------------------------------------------------------------- /checkstyle/import-control-core.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /gradle/eclipse.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | def gradleProject = project 12 | plugins.withId('eclipse') { 13 | if (gradleProject != gradleProject.rootProject) { 14 | eclipse { 15 | project { 16 | name = "${gradleProject.rootProject.name}${gradleProject.path.replace(':', '-')}" 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /documentation/src/docs/contributing.md: -------------------------------------------------------------------------------- 1 | 10 | # Contributing to Pravega 11 | 12 | * [Contributions guidelines](https://github.com/pravega/pravega/wiki/Contributing) 13 | * [Issue triaging and labeling](https://github.com/pravega/pravega/wiki/Issues-Triaging-and-Labeling) 14 | * [Review process](https://github.com/pravega/pravega/wiki/Pull-Request-and-Reviews) 15 | 16 | Happy hacking! 17 | -------------------------------------------------------------------------------- /gradle/spotbugs.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | 12 | 13 | plugins.withId('com.github.spotbugs') { 14 | spotbugs { 15 | toolVersion = spotbugsVersion 16 | effort = "max" 17 | includeFilter = file("$rootDir/checkstyle/spotbugs-include.xml") 18 | excludeFilter = file("$rootDir/checkstyle/spotbugs-exclude.xml") 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | rootProject.name = 'schema-registry' 12 | 13 | include 'client', 14 | 'common', 15 | 'contract', 16 | 'server', 17 | 'auth', 18 | 'serializers:shared', 19 | 'serializers:protobuf', 20 | 'serializers:json', 21 | 'serializers:avro', 22 | 'serializers', 23 | 'test' 24 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/RegistryServiceException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Base class for all Registry Service Exceptions. 14 | */ 15 | public abstract class RegistryServiceException extends RuntimeException { 16 | public RegistryServiceException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/Etag.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage; 11 | 12 | /** 13 | * An entity tag for a group. All group metadata is written with optimistic concurrency using atomic compare and swap 14 | * on metadata and the Group's entity tag. 15 | * @param Type of entity tag. 16 | */ 17 | public interface Etag { 18 | T etag(); 19 | } 20 | -------------------------------------------------------------------------------- /test/src/main/java/io/pravega/schemaregistry/integrationtest/Address.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class Address { 20 | private String streetAddress; 21 | private String city; 22 | } 23 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/CustomSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 13 | 14 | import java.io.OutputStream; 15 | 16 | public interface CustomSerializer { 17 | void serialize(T var, SchemaInfo schema, OutputStream outputStream); 18 | } 19 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Exception thrown when server isnt able to find the requested resource. 14 | */ 15 | public class ResourceNotFoundException extends RegistryServiceException { 16 | public ResourceNotFoundException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/CustomDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 13 | 14 | import java.io.InputStream; 15 | 16 | public interface CustomDeserializer { 17 | T deserialize(InputStream inputStream, SchemaInfo writerSchema, SchemaInfo readerSchema); 18 | } 19 | -------------------------------------------------------------------------------- /serializers/shared/src/test/java/io/pravega/schemaregistry/serializer/shared/testobjs/Address.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.testobjs; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class Address { 20 | private String streetAddress; 21 | private String city; 22 | } 23 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/ResultPage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry; 11 | 12 | import lombok.Data; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Page result object that contains a list of entries and a continuation token. 18 | * 19 | * @param Type of result. 20 | */ 21 | @Data 22 | public class ResultPage { 23 | private final List list; 24 | private final C token; 25 | } 26 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/CodecTypeNotRegisteredException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Exception thrown when a codec type is not registered for the group. 14 | */ 15 | public class CodecTypeNotRegisteredException extends RegistryServiceException { 16 | public CodecTypeNotRegisteredException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /charts/schema-registry/templates/service_account.yaml: -------------------------------------------------------------------------------- 1 | # /** 2 | # * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # * 4 | # * Licensed under the Apache License, Version 2.0 (the "License"); 5 | # * you may not use this file except in compliance with the License. 6 | # * You may obtain a copy of the License at 7 | # * 8 | # * http://www.apache.org/licenses/LICENSE-2.0 9 | # */ 10 | 11 | {{- if .Values.serviceAccount.create }} 12 | apiVersion: v1 13 | kind: ServiceAccount 14 | metadata: 15 | name: {{ .Values.serviceAccount.name }} 16 | namespace: {{ .Release.Namespace }} 17 | labels: 18 | {{ include "schema-registry.commonLabels" . | indent 4 }} 19 | annotations: 20 | {{ toYaml .Values.serviceAccount.annotations | indent 4 }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /docker/pravega-schema-registry/scripts/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | 12 | set -eo pipefail 13 | 14 | DIR=/opt/schema-registry 15 | SCRIPTS_DIR=${DIR}/scripts 16 | 17 | source ${SCRIPTS_DIR}/common.sh 18 | source ${SCRIPTS_DIR}/init_schemaregistry.sh 19 | 20 | if [ ${WAIT_FOR} ];then 21 | ${SCRIPTS_DIR}/wait_for 22 | fi 23 | 24 | if [[ -n "$PRE_START_CMD" ]];then 25 | $PRE_START_CMD 26 | fi 27 | 28 | exec /opt/schema-registry/bin/schema-registry 29 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/PreconditionFailedException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Exception thrown when conditional updates to an entity are attempted and condition fails. 14 | */ 15 | public class PreconditionFailedException extends RegistryServiceException { 16 | public PreconditionFailedException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/IncompatibleSchemaException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Exception thrown when a schema fails the compatibility checks for the group's compatibility policy. 14 | */ 15 | public class IncompatibleSchemaException extends RegistryServiceException { 16 | public IncompatibleSchemaException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/src/test/java/io/pravega/schemaregistry/integrationtest/TestInMemoryEndToEnd.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import io.pravega.schemaregistry.storage.SchemaStore; 13 | import io.pravega.schemaregistry.storage.SchemaStoreFactory; 14 | 15 | public class TestInMemoryEndToEnd extends TestEndToEnd { 16 | SchemaStore getStore() { 17 | return SchemaStoreFactory.createInMemoryStore(executor); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/BaseDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import io.pravega.client.stream.Serializer; 13 | 14 | import java.nio.ByteBuffer; 15 | 16 | abstract class BaseDeserializer implements Serializer { 17 | @Override 18 | public final ByteBuffer serialize(T value) { 19 | throw new UnsupportedOperationException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/BaseSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import io.pravega.client.stream.Serializer; 13 | 14 | import java.nio.ByteBuffer; 15 | 16 | abstract class BaseSerializer implements Serializer { 17 | @Override 18 | public final T deserialize(ByteBuffer serializedValue) { 19 | throw new UnsupportedOperationException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/exceptions/SerializationFormatMismatchException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.exceptions; 11 | 12 | /** 13 | * Exception thrown when a serialization format is different from the group property's serialization format. 14 | */ 15 | public class SerializationFormatMismatchException extends RegistryServiceException { 16 | public SerializationFormatMismatchException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | UTF-8 15 | %d %-4relative [%thread] %-5level %logger{35} - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/src/main/java/io/pravega/schemaregistry/integrationtest/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | public class User { 21 | @Getter 22 | private String name; 23 | @Getter 24 | private Address address; 25 | @Getter 26 | private int age; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /serializers/shared/src/test/java/io/pravega/schemaregistry/serializer/shared/testobjs/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.testobjs; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | public class User { 21 | @Getter 22 | private String name; 23 | @Getter 24 | private Address address; 25 | @Getter 26 | private int age; 27 | } 28 | -------------------------------------------------------------------------------- /gradle/idea.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | plugins.withId('idea') { 12 | idea.project?.ipr { 13 | withXml { provider -> 14 | // Add support for annotation processing which is needed by the lombok plugin 15 | provider.node.component 16 | .find { it.@name == 'CompilerConfiguration' } 17 | .annotationProcessing.replaceNode { 18 | annotationProcessing { 19 | profile(name: 'Default', default: true, enabled: true) 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /test/src/main/java/io/pravega/schemaregistry/integrationtest/DerivedUser1.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @EqualsAndHashCode(callSuper = true) 20 | public class DerivedUser1 extends User { 21 | @Getter 22 | private String user1; 23 | 24 | public DerivedUser1(String name, Address address, int age, String user1) { 25 | super(name, address, age); 26 | this.user1 = user1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/src/main/java/io/pravega/schemaregistry/integrationtest/DerivedUser2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @EqualsAndHashCode(callSuper = true) 20 | public class DerivedUser2 extends User { 21 | @Getter 22 | private String user2; 23 | 24 | public DerivedUser2(String name, Address address, int age, String user2) { 25 | super(name, address, age); 26 | this.user2 = user2; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /serializers/shared/src/test/java/io/pravega/schemaregistry/serializer/shared/testobjs/DerivedUser1.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.testobjs; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @EqualsAndHashCode(callSuper = true) 20 | public class DerivedUser1 extends User { 21 | @Getter 22 | private String user1; 23 | 24 | public DerivedUser1(String name, Address address, int age, String user1) { 25 | super(name, address, age); 26 | this.user1 = user1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /serializers/shared/src/test/java/io/pravega/schemaregistry/serializer/shared/testobjs/DerivedUser2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.testobjs; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @EqualsAndHashCode(callSuper = true) 20 | public class DerivedUser2 extends User { 21 | @Getter 22 | private String user2; 23 | 24 | public DerivedUser2(String name, Address address, int age, String user2) { 25 | super(name, address, age); 26 | this.user2 = user2; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docker/pravega-schema-registry/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | FROM openjdk:11.0-jre-slim 11 | 12 | RUN apt-get update && apt-get install -y -q \ 13 | curl \ 14 | rpcbind \ 15 | python \ 16 | jq \ 17 | curl \ 18 | net-tools \ 19 | iproute2 \ 20 | 21 | && rm -rf /var/lib/apt/lists/* 22 | 23 | EXPOSE 9092 24 | 25 | WORKDIR /opt/schema-registry 26 | 27 | COPY pravega-schema-registry/ /opt/schema-registry/ 28 | COPY scripts/ /opt/schema-registry/scripts/ 29 | 30 | # Default shell of jdk11 image is dash 31 | # Creating symlink to point to bash 32 | RUN ln -sf /bin/bash /bin/sh 33 | 34 | RUN chmod +x -R /opt/schema-registry/scripts/ 35 | 36 | ENTRYPOINT [ "/opt/schema-registry/scripts/entrypoint.sh" ] 37 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/client/Version.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.client; 11 | 12 | import io.pravega.client.tables.impl.TableSegmentKeyVersion; 13 | import lombok.AllArgsConstructor; 14 | import lombok.EqualsAndHashCode; 15 | 16 | @AllArgsConstructor 17 | @EqualsAndHashCode 18 | public class Version { 19 | public static final Version NON_EXISTENT = new Version(TableSegmentKeyVersion.NOT_EXISTS.getSegmentVersion()); 20 | public static final Version NO_VERSION = new Version(TableSegmentKeyVersion.NO_VERSION.getSegmentVersion()); 21 | 22 | private final long version; 23 | 24 | public long toLong() { 25 | return version; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /charts/schema-registry/templates/service.yaml: -------------------------------------------------------------------------------- 1 | # /** 2 | # * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # * 4 | # * Licensed under the Apache License, Version 2.0 (the "License"); 5 | # * you may not use this file except in compliance with the License. 6 | # * You may obtain a copy of the License at 7 | # * 8 | # * http://www.apache.org/licenses/LICENSE-2.0 9 | # */ 10 | 11 | {{ $svc := .Values.service }} 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: {{ template "schema-registry.fullname" . }} 16 | namespace: {{ .Release.Namespace }} 17 | labels: 18 | {{ include "schema-registry.commonLabels" . | indent 4 }} 19 | {{- if $svc.labels }} 20 | {{ toYaml $svc.labels | indent 4 }} 21 | {{- end }} 22 | annotations: 23 | {{ toYaml $svc.annotations | indent 4 }} 24 | spec: 25 | type: {{ $svc.type }} 26 | ports: 27 | - port: {{ $svc.port }} 28 | targetPort: {{ $svc.port }} 29 | protocol: TCP 30 | name: rest 31 | selector: 32 | {{ include "schema-registry.selectorLabels" . | indent 4 }} 33 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/server/rest/resources/PingImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest.resources; 11 | 12 | import io.pravega.schemaregistry.contract.v1.ApiV1; 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | import javax.ws.rs.core.Response; 16 | import javax.ws.rs.core.Response.Status; 17 | 18 | /* 19 | Implementation of Ping, which serves as a check for working REST server. 20 | */ 21 | @Slf4j 22 | public class PingImpl implements ApiV1.Ping { 23 | 24 | /** 25 | * Implementation of Ping API. 26 | * 27 | * @return Response 200 OK 28 | */ 29 | @Override 30 | public Response ping() { 31 | return Response.status(Status.OK).build(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/SchemaWithVersion.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NonNull; 16 | 17 | /** 18 | * Object that encapsulates schemaInfo with its associated version. 19 | */ 20 | @Data 21 | @Builder 22 | @AllArgsConstructor 23 | public class SchemaWithVersion { 24 | /** 25 | * Schema Information object. 26 | */ 27 | private @NonNull final SchemaInfo schemaInfo; 28 | /** 29 | * Version information object that identifies the corresponding schema object. 30 | */ 31 | private @NonNull final VersionInfo versionInfo; 32 | } 33 | -------------------------------------------------------------------------------- /docker/pravega-schema-registry/scripts/wait_for: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python -u 2 | # 3 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | 12 | from time import sleep 13 | 14 | import os 15 | import socket 16 | 17 | endpoints = os.environ["WAIT_FOR"].split(",") 18 | size = 1024 19 | 20 | for endpoint in endpoints: 21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | print("Waiting for " + endpoint) 23 | connected = False 24 | while not connected: 25 | try: 26 | host,port = endpoint.split(":") 27 | s.connect((host,int(port))) 28 | connected = True 29 | print("Connected to " + endpoint) 30 | except Exception as e: 31 | print("Unable to connect to " + endpoint + ". Waiting") 32 | print(e) 33 | sleep(5) 34 | -------------------------------------------------------------------------------- /gradle/checkstyle.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | plugins.withId('checkstyle') { 12 | checkstyle { 13 | toolVersion = checkstyleToolVersion 14 | 15 | configFile = new File(rootDir, "checkstyle/checkstyle.xml") 16 | configProperties = [importControlFile: "$rootDir/checkstyle/import-control.xml", 17 | suppressionsFile: "$rootDir/checkstyle/suppressions.xml"] 18 | } 19 | 20 | plugins.withId('java') { 21 | checkstyle { 22 | // Exclude generated code from Checkstyle checks 23 | checkstyleMain.exclude '**/io.pravega.schemaregistry.contract/generated/**' 24 | checkstyleMain.exclude '**/io.pravega.schemaregistry.tests.integrationtest/generated/**' 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/server/rest/RegistryApplication.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest; 11 | 12 | import javax.ws.rs.core.Application; 13 | import java.util.Set; 14 | 15 | /** 16 | * Application to register the REST resource classes. 17 | */ 18 | public class RegistryApplication extends Application { 19 | private final Set resource; 20 | 21 | public RegistryApplication(final Set resources) { 22 | super(); 23 | resource = resources; 24 | } 25 | 26 | /** 27 | * Get a set of root resources. 28 | * 29 | * @return a set of root resource instances. 30 | */ 31 | @Override 32 | public Set getSingletons() { 33 | return resource; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/server/rest/resources/AuthResources.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest.resources; 11 | 12 | import io.pravega.schemaregistry.service.Config; 13 | 14 | class AuthResources { 15 | static final String DOMAIN = Config.DOMAIN_RESOURCE_QUALIFIER + "::/"; 16 | static final String DEFAULT_NAMESPACE = ""; 17 | static final String NAMESPACE_FORMAT = DOMAIN + Config.NAMESPACE_RESOURCE_QUALIFIER + ":%s"; 18 | static final String NAMESPACE_GROUP_FORMAT = NAMESPACE_FORMAT + "/" + Config.GROUP_RESOURCE_QUALIFIER + ":%s"; 19 | static final String NAMESPACE_GROUP_SCHEMA_FORMAT = NAMESPACE_GROUP_FORMAT + "/schemas:*"; 20 | static final String NAMESPACE_GROUP_CODEC_FORMAT = NAMESPACE_GROUP_FORMAT + "/codecs:*"; 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/io/pravega/schemaregistry/common/HashUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import lombok.SneakyThrows; 13 | 14 | import java.math.BigInteger; 15 | import java.security.MessageDigest; 16 | import java.security.NoSuchAlgorithmException; 17 | 18 | public class HashUtil { 19 | private static final String SHA_256 = "SHA-256"; 20 | 21 | /** 22 | * Computes a 256 bit hash of supplied bytes using sha-256 hash function. 23 | * 24 | * @param bytes bytes to compute hash of. 25 | * @return a 256 bit hash of the given bytes. 26 | */ 27 | @SneakyThrows(NoSuchAlgorithmException.class) 28 | public static BigInteger getFingerprint(byte[] bytes) { 29 | MessageDigest md = MessageDigest.getInstance(SHA_256); 30 | 31 | return new BigInteger(1, md.digest(bytes)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gradle/rat.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | apply plugin: "org.nosphere.apache.rat" 12 | 13 | rat { 14 | excludes = [ 15 | '**/.*/**', 16 | '**/*.iml', 17 | '**/*.iws', 18 | '**/*.ipr', 19 | '**/*passwd', 20 | '**/gradle/wrapper/**', 21 | '**/build/**', 22 | '**/out/**', 23 | '**/generated/**', 24 | '**/checkstyle/**', 25 | 'deployment/aws/installer/hosts-template', 26 | 'lombok.config', 27 | '**/*.log', 28 | '**/*.log.gz', 29 | '**/*.tmp', 30 | '**/*.lock', 31 | '**/*.json', 32 | '**/*.proto', 33 | '**/*.avsc', 34 | '**/config/*jks*', 35 | '**/config/*.crt', 36 | '**/config/*.key', 37 | 'CODE_OF_CONDUCT.md' 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/rules/AlwaysTrueCompatibilityChecker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.rules; 11 | 12 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Always true implementation of Compatibility Checker that returns true for each of the checks. 18 | */ 19 | public class AlwaysTrueCompatibilityChecker implements CompatibilityChecker { 20 | @Override 21 | public boolean canRead(SchemaInfo readUsing, List writtenUsing) { 22 | return true; 23 | } 24 | 25 | @Override 26 | public boolean canBeRead(SchemaInfo writtenUsing, List readUsing) { 27 | return true; 28 | } 29 | 30 | @Override 31 | public boolean canMutuallyRead(SchemaInfo schema, List schemaList) { 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/ContinuationToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage; 11 | 12 | import com.google.common.base.Strings; 13 | 14 | public class ContinuationToken { 15 | public static final ContinuationToken EMPTY = new ContinuationToken(""); 16 | private final String token; 17 | 18 | private ContinuationToken(String token) { 19 | this.token = token; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return token; 25 | } 26 | 27 | public static ContinuationToken create(String token) { 28 | return fromString(token); 29 | } 30 | 31 | public static ContinuationToken fromString(String token) { 32 | if (Strings.isNullOrEmpty(token)) { 33 | return EMPTY; 34 | } else { 35 | return new ContinuationToken(token); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/schemas/Schema.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.schemas; 11 | 12 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 13 | 14 | /** 15 | * Interface for container class for schemas for different serialization formats. 16 | * 17 | * @param Type of object. 18 | */ 19 | public interface Schema { 20 | /** 21 | * Returns the {@link SchemaInfo} object that is computed from the schema object. SchemaInfo is the object that encapsulates 22 | * all schema metadata to be shared with the schema registry service. 23 | * 24 | * @return Schema Info object derived from the schema object. 25 | */ 26 | SchemaInfo getSchemaInfo(); 27 | 28 | /** 29 | * Class for the Type of object. 30 | * 31 | * @return Class of type T 32 | */ 33 | Class getTClass(); 34 | } 35 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/EncodingInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import lombok.Data; 13 | import lombok.NonNull; 14 | 15 | /** 16 | * Encoding Info describes the details of encoding for each event payload. Each combination of schema version and codec type 17 | * is uniquely identified by an {@link EncodingId}. 18 | * The registry service exposes APIs to generate or resolve {@link EncodingId} to {@link EncodingInfo}. 19 | */ 20 | @Data 21 | public class EncodingInfo { 22 | /** 23 | * Version of the schema which is used in encoding the data. 24 | */ 25 | private @NonNull final VersionInfo versionInfo; 26 | /** 27 | * Actual schema which is used in encoding the data. 28 | */ 29 | private @NonNull final SchemaInfo schemaInfo; 30 | /** 31 | * Codec type which is used in encoding the data. 32 | */ 33 | private @NonNull final CodecType codecType; 34 | } 35 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/codec/Decoder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.codec; 11 | 12 | import java.io.IOException; 13 | import java.nio.ByteBuffer; 14 | import java.util.Map; 15 | 16 | /** 17 | * Decoder interface that defines method to decode data. 18 | */ 19 | @FunctionalInterface 20 | public interface Decoder { 21 | /** 22 | * Implementation should decode the remaining bytes in the buffer and return a new ByteBuffer that includes 23 | * the decoded data at its current position. 24 | * 25 | * @param data encoded ByteBuffer to decode. 26 | * @param codecProperties codec properties. 27 | * @return decoded ByteBuffer with position set to the start of decoded data. 28 | * @throws IOException can be thrown while reading from or writing to byte buffers. 29 | */ 30 | ByteBuffer decode(ByteBuffer data, Map codecProperties) throws IOException; 31 | } 32 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/MultiplexedSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Serializer to multiplex serialization of multiple types of events with same serialization format. 17 | * 18 | * @param Type of object. 19 | */ 20 | public class MultiplexedSerializer extends BaseSerializer { 21 | private final Map, AbstractSerializer> serializers; 22 | 23 | public MultiplexedSerializer(Map, AbstractSerializer> serializers) { 24 | this.serializers = serializers; 25 | } 26 | 27 | @Override 28 | @SuppressWarnings("unchecked") 29 | public ByteBuffer serialize(T obj) { 30 | Class tClass = (Class) obj.getClass(); 31 | AbstractSerializer serializer = serializers.get(tClass); 32 | return serializer.serialize(obj); 33 | } 34 | } -------------------------------------------------------------------------------- /client/src/test/java/io/pravega/schemaregistry/client/SchemaRegistryClientTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.client; 11 | 12 | import java.net.URI; 13 | import org.junit.Test; 14 | import static org.junit.Assert.*; 15 | 16 | public class SchemaRegistryClientTest { 17 | @Test 18 | public void testClientFactory() throws Exception { 19 | URI schemaRegistryUri = URI.create("http://localhost:9092"); 20 | SchemaRegistryClientConfig config = SchemaRegistryClientConfig.builder() 21 | .schemaRegistryUri(schemaRegistryUri) 22 | .build(); 23 | 24 | SchemaRegistryClient client = SchemaRegistryClientFactory.withDefaultNamespace(config); 25 | assertNull(client.getNamespace()); 26 | client.close(); 27 | client = SchemaRegistryClientFactory.withNamespace("a", config); 28 | 29 | assertEquals("a", client.getNamespace()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/codec/Codec.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.codec; 11 | 12 | import io.pravega.schemaregistry.contract.data.CodecType; 13 | import io.pravega.schemaregistry.contract.data.EncodingInfo; 14 | 15 | /** 16 | * Codec interface extends {@link Encoder} and {@link Decoder} interfaces that defines methods to encode and decode 17 | * data. Encoder interface takes a codec type and encoding function. Decoder interface defines a decoding function. 18 | */ 19 | public interface Codec extends Encoder, Decoder { 20 | /** 21 | * Name identifying the Codec Type. 22 | * This name should be same as the {@link CodecType#getName()} that is registered for the group in schema registry 23 | * service. 24 | * The deserializers will find the decoder for the encoded data from {@link EncodingInfo#getCodecType()} by matching 25 | * the name. 26 | * 27 | * @return Name of the codec. 28 | */ 29 | String getName(); 30 | } 31 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/EncodingId.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import io.pravega.common.ObjectBuilder; 13 | import lombok.AllArgsConstructor; 14 | import lombok.Builder; 15 | import lombok.Data; 16 | 17 | /** 18 | * For each group unique set of Encoding Ids are generated for each unique combination of schema version and codec types 19 | * registered in the group. 20 | * The encoding id will typically be attached to the encoded data in a header to describe how to parse the following data. 21 | * The registry service exposes APIs to resolve encoding id to {@link EncodingInfo} objects that include details about the 22 | * encoding used. 23 | */ 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | public class EncodingId { 28 | /** 29 | * A 4byte id that uniquely identifies a {@link VersionInfo} and codecType pair. 30 | */ 31 | private final int id; 32 | 33 | public static class EncodingIdBuilder implements ObjectBuilder { 34 | } 35 | } -------------------------------------------------------------------------------- /charts/schema-registry/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | # /** 2 | # * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # * 4 | # * Licensed under the Apache License, Version 2.0 (the "License"); 5 | # * you may not use this file except in compliance with the License. 6 | # * You may obtain a copy of the License at 7 | # * 8 | # * http://www.apache.org/licenses/LICENSE-2.0 9 | # */ 10 | 11 | {{- $ingress := .Values.ingress -}} 12 | {{- $svc := .Values.service -}} 13 | {{- if $ingress.enabled -}} 14 | apiVersion: networking.k8s.io/v1beta1 15 | kind: Ingress 16 | metadata: 17 | name: {{ template "schema-registry.fullname" . }} 18 | labels: 19 | {{ include "schema-registry.commonLabels" . | indent 4 }} 20 | annotations: 21 | {{ toYaml $ingress.annotations | indent 4 }} 22 | spec: 23 | {{- if $ingress.tls }} 24 | tls: 25 | {{- range $ingress.tls }} 26 | - hosts: 27 | {{- range .hosts }} 28 | - {{ . | quote }} 29 | {{- end }} 30 | secretName: {{ .secretName }} 31 | {{- end }} 32 | {{- end }} 33 | rules: 34 | {{- range $ingress.hosts }} 35 | - host: {{ . }} 36 | http: 37 | paths: 38 | - path: {{ $ingress.path }} 39 | backend: 40 | serviceName: {{ template "schema-registry.fullname" $ }} 41 | servicePort: {{ $svc.port }} 42 | {{- end }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /client/src/main/java/io/pravega/schemaregistry/client/AuthFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.client; 11 | 12 | import io.pravega.schemaregistry.common.AuthHelper; 13 | import io.pravega.schemaregistry.common.CredentialProvider; 14 | import lombok.AllArgsConstructor; 15 | 16 | import javax.ws.rs.client.ClientRequestContext; 17 | import javax.ws.rs.client.ClientRequestFilter; 18 | import javax.ws.rs.core.HttpHeaders; 19 | 20 | /** 21 | * Authentication filter for the client. This intercepts requests and adds authentication/authorization header 22 | * to the request. The credentials to add are retrieved from credential provider. 23 | */ 24 | @AllArgsConstructor 25 | public class AuthFilter implements ClientRequestFilter { 26 | private final CredentialProvider credentialProvider; 27 | 28 | @Override 29 | public void filter(ClientRequestContext context) { 30 | context.getHeaders().add(HttpHeaders.AUTHORIZATION, 31 | AuthHelper.getAuthorizationHeader(credentialProvider.getMethod(), credentialProvider.getToken())); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/src/test/java/io/pravega/schemaregistry/integrationtest/TestPravegaEndToEnd.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import io.pravega.client.ClientConfig; 13 | import io.pravega.schemaregistry.pravegastandalone.PravegaStandaloneUtils; 14 | import io.pravega.schemaregistry.storage.SchemaStore; 15 | import io.pravega.schemaregistry.storage.SchemaStoreFactory; 16 | import org.junit.Before; 17 | 18 | import java.net.URI; 19 | 20 | public class TestPravegaEndToEnd extends TestEndToEnd { 21 | private ClientConfig clientConfig; 22 | 23 | @Before 24 | public void startPravega() { 25 | PravegaStandaloneUtils pravegaStandaloneUtils = PravegaStandaloneUtils.startPravega(); 26 | clientConfig = ClientConfig.builder().controllerURI(URI.create(pravegaStandaloneUtils.getControllerURI())).build(); 27 | } 28 | 29 | SchemaStore getStore() { 30 | if (clientConfig == null) { 31 | startPravega(); 32 | } 33 | return SchemaStoreFactory.createPravegaStore(clientConfig, executor); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/rules/CompatibilityCheckerFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.rules; 11 | 12 | import io.pravega.schemaregistry.contract.data.SerializationFormat; 13 | 14 | /** 15 | * Factory for compatibility checkers. 16 | * Currently we only have implementation for avro compatibility checker. 17 | * For all other SerializationFormat the default {@link AlwaysTrueCompatibilityChecker} is used. 18 | */ 19 | public class CompatibilityCheckerFactory { 20 | private static final AvroCompatibilityChecker AVRO_COMPATIBILITY_CHECKER = new AvroCompatibilityChecker(); 21 | private static final AlwaysTrueCompatibilityChecker ALWAYS_TRUE_COMPATIBILITY_CHECKER = new AlwaysTrueCompatibilityChecker(); 22 | 23 | public static CompatibilityChecker getCompatibilityChecker(SerializationFormat serializationFormat) { 24 | if (serializationFormat.equals(SerializationFormat.Avro)) { 25 | return AVRO_COMPATIBILITY_CHECKER; 26 | } else { 27 | return ALWAYS_TRUE_COMPATIBILITY_CHECKER; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /auth/src/main/java/io/pravega/schemaregistry/common/CredentialProvider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import lombok.AllArgsConstructor; 13 | 14 | /** 15 | * This interface represents the credentials passed to Schema registry client. 16 | */ 17 | public interface CredentialProvider { 18 | /** 19 | * Returns the authentication method to be used. 20 | * 21 | * @return the authentication method for these credentials. 22 | */ 23 | String getMethod(); 24 | 25 | /** 26 | * Returns the token to be sent to Schema registry service. 27 | * 28 | * @return A token string. 29 | */ 30 | String getToken(); 31 | 32 | @AllArgsConstructor 33 | class DefaultCredentialProvider implements CredentialProvider { 34 | private final String authMethod; 35 | private final String authToken; 36 | 37 | @Override 38 | public String getMethod() { 39 | return authMethod; 40 | } 41 | 42 | @Override 43 | public String getToken() { 44 | return authToken; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/codec/Encoder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.codec; 11 | 12 | import io.pravega.schemaregistry.contract.data.CodecType; 13 | 14 | import java.io.IOException; 15 | import java.io.OutputStream; 16 | import java.nio.ByteBuffer; 17 | 18 | /** 19 | * Defines method to encode data. 20 | */ 21 | public interface Encoder { 22 | /** 23 | * Codec type for the encoder. 24 | * 25 | * @return Codec Type for the encoder. 26 | */ 27 | CodecType getCodecType(); 28 | 29 | /** 30 | * Implementation should encode the remaining bytes in the buffer and return a new ByteBuffer that includes 31 | * the encoded data at its current position. 32 | * 33 | * The implementation can optionally call flush or close on outputstream with no consequence. 34 | * 35 | * @param data ByteBuffer to encode. 36 | * @param outputStream OutputStream where the encoded data should be written. 37 | * @throws IOException IOException can be thrown while reading from or writing to byte buffers. 38 | */ 39 | void encode(ByteBuffer data, OutputStream outputStream) throws IOException; 40 | } 41 | -------------------------------------------------------------------------------- /serializers/protobuf/src/main/java/io/pravega/schemaregistry/serializer/protobuf/impl/ProtobufSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.protobuf.impl; 11 | 12 | import com.google.protobuf.Message; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.serializer.shared.codec.Encoder; 15 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 16 | import io.pravega.schemaregistry.serializer.protobuf.schemas.ProtobufSchema; 17 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractSerializer; 18 | 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | 22 | public class ProtobufSerializer extends AbstractSerializer { 23 | public ProtobufSerializer(String groupId, SchemaRegistryClient client, ProtobufSchema schema, 24 | Encoder encoder, boolean registerSchema, boolean encodeHeader) { 25 | super(groupId, client, schema, encoder, registerSchema, encodeHeader); 26 | } 27 | 28 | @Override 29 | protected void serialize(T var, SchemaInfo schemaInfo, OutputStream outputStream) throws IOException { 30 | var.writeTo(outputStream); 31 | outputStream.flush(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /documentation/src/mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | site_name: 'Exploring Pravega' 10 | site_url: 'https://pravega.io/' 11 | site_description: 'Documentation to help you get familiar with Pravega' 12 | 13 | repo_url: 'https://github.com/pravega/schema-registry' 14 | edit_uri: 'tree/master/documentation/src/docs' 15 | 16 | theme: 'material' 17 | 18 | 19 | # Extensions 20 | markdown_extensions: 21 | - admonition 22 | - codehilite(guess_lang=false) 23 | - footnotes 24 | - meta 25 | - toc(permalink=true) 26 | - pymdownx.betterem(smart_enable=all) 27 | - pymdownx.caret 28 | - pymdownx.inlinehilite 29 | - pymdownx.magiclink 30 | - pymdownx.smartsymbols 31 | - pymdownx.superfences 32 | 33 | pages: 34 | - Overview: 'overview.md' 35 | - Understanding Schema Registry: 36 | - 'Schema Registry Concepts': 'schema-registry-concepts.md' 37 | 38 | - Using Schema Registry SDK: 39 | - 'REST API': 'rest-documentation.md' 40 | - 'Using schema registry in Pravega Applications': 'pravega-applications.md' 41 | 42 | - Running Schema Registry: 43 | - 'Deployment Overview': 'installation-guide.md' 44 | 45 | - Security: 46 | - 'Security(TLS) and Authorization/Authentication': 'security.md' 47 | extra: 48 | version: 0.1 49 | 50 | google_analytics: ['UA-1508605-1', 'pravega.io'] 51 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/server/rest/CustomJsonParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest; 11 | 12 | import com.fasterxml.jackson.annotation.JsonInclude; 13 | import com.fasterxml.jackson.databind.DeserializationFeature; 14 | import com.fasterxml.jackson.databind.ObjectMapper; 15 | 16 | import javax.ws.rs.ext.ContextResolver; 17 | 18 | /** 19 | * Class to define custom json parser for the Jersey web application. 20 | */ 21 | public class CustomJsonParser implements ContextResolver { 22 | 23 | final ObjectMapper defaultObjectMapper; 24 | 25 | /** 26 | * Creates an instance of the JSON parser. 27 | */ 28 | public CustomJsonParser() { 29 | defaultObjectMapper = createDefaultMapper(); 30 | } 31 | 32 | @Override 33 | public ObjectMapper getContext(Class type) { 34 | return defaultObjectMapper; 35 | } 36 | 37 | private static ObjectMapper createDefaultMapper() { 38 | final ObjectMapper result = new ObjectMapper(); 39 | 40 | // Allow extra unknown fields in the JSON objects. 41 | result.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 42 | result.setSerializationInclusion(JsonInclude.Include.NON_NULL); 43 | 44 | return result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/io/pravega/schemaregistry/common/Either.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import com.google.common.base.Preconditions; 13 | import lombok.Data; 14 | 15 | /** 16 | * A holder object consisting of either of two elements. 17 | * 18 | * The objects could be of any type. Exactly one of the values will exist while the other will be null. 19 | * If a mutable object is stored in 'Either', then 'Either' itself effectively becomes mutable. 20 | * 21 | * @param the left element type. 22 | * @param the right element type. 23 | */ 24 | @Data 25 | public class Either { 26 | private final T left; 27 | private final K right; 28 | 29 | private Either(T left, K right) { 30 | this.left = left; 31 | this.right = right; 32 | } 33 | 34 | public static Either left(T t) { 35 | Preconditions.checkNotNull(t); 36 | return new Either(t, null); 37 | } 38 | 39 | public static Either right(K k) { 40 | Preconditions.checkNotNull(k); 41 | return new Either(null, k); 42 | } 43 | 44 | public boolean isLeft() { 45 | return left != null; 46 | } 47 | 48 | public boolean isRight() { 49 | return right != null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /client/src/main/java/io/pravega/schemaregistry/client/SchemaRegistryClientFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.client; 11 | 12 | /** 13 | * Factory class for creating Schema Registry client. 14 | */ 15 | public class SchemaRegistryClientFactory { 16 | /** 17 | * Factory method to create Schema Registry Client with default namespace. 18 | * This sets the namespace context to use the default namespace (no namespace). 19 | * 20 | * @param config Configuration for creating registry client. 21 | * @return SchemaRegistry client implementation 22 | */ 23 | public static SchemaRegistryClient withDefaultNamespace(SchemaRegistryClientConfig config) { 24 | return new SchemaRegistryClientImpl(config, null); 25 | } 26 | 27 | /** 28 | * Factory method to create Schema Registry Client with namespace. 29 | * This sets the namespace context for all calls to registry service. 30 | * 31 | * @param config Configuration for creating registry client. 32 | * @param namespace Namespace 33 | * @return SchemaRegistry client implementation 34 | */ 35 | public static SchemaRegistryClient withNamespace(String namespace, SchemaRegistryClientConfig config) { 36 | return new SchemaRegistryClientImpl(config, namespace); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/SchemaStoreFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage; 11 | 12 | import io.pravega.client.ClientConfig; 13 | import io.pravega.schemaregistry.storage.client.TableStore; 14 | import io.pravega.schemaregistry.storage.impl.SchemaStoreImpl; 15 | import io.pravega.schemaregistry.storage.impl.groups.InMemoryGroups; 16 | import io.pravega.schemaregistry.storage.impl.groups.PravegaKeyValueGroups; 17 | import io.pravega.schemaregistry.storage.impl.schemas.InMemorySchemas; 18 | import io.pravega.schemaregistry.storage.impl.schemas.PravegaKeyValueSchemas; 19 | 20 | import java.util.concurrent.ScheduledExecutorService; 21 | 22 | /** 23 | * Factory for creating schema store of different types. 24 | */ 25 | public class SchemaStoreFactory { 26 | public static SchemaStore createInMemoryStore(ScheduledExecutorService executor) { 27 | return new SchemaStoreImpl<>(new InMemoryGroups(executor), new InMemorySchemas()); 28 | } 29 | 30 | public static SchemaStore createPravegaStore(ClientConfig clientConfig, ScheduledExecutorService executor) { 31 | TableStore tableStore = new TableStore(clientConfig, executor); 32 | tableStore.startAsync(); 33 | tableStore.awaitRunning(); 34 | return new SchemaStoreImpl<>(new PravegaKeyValueGroups(tableStore, executor), new PravegaKeyValueSchemas(tableStore)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gradle/application.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | import java.util.regex.Matcher 12 | 13 | plugins.withId('application') { 14 | configurations.archives.with { 15 | artifacts.remove artifacts.find { it.hasProperty('archiveTask') && it.archiveTask.is(distZip) } 16 | artifacts.remove artifacts.find { it.hasProperty('archiveTask') && it.archiveTask.is(distTar) } 17 | } 18 | 19 | task pathingJar(type: Jar) { 20 | appendix = 'pathing' 21 | 22 | // Delay configuring the manifest to avoid resolving the configuration 23 | doFirst { 24 | manifest { 25 | attributes("Class-Path": 26 | configurations.runtime.collect { it.name }.join(' ') + ' ' + 27 | jar.archiveName 28 | ) 29 | } 30 | } 31 | } 32 | applicationDistribution.from(pathingJar) { 33 | into "lib" 34 | } 35 | 36 | startScripts { 37 | doLast { 38 | unixScript.text = unixScript.text.replace('PRAVEGA_APP_HOME', '\$APP_HOME') 39 | windowsScript.text = windowsScript.text.replace('PRAVEGA_APP_HOME', '%~dp0..') 40 | // Replace the classpath on windows with the pathing JAR and the main archive 41 | windowsScript.text = windowsScript.text.replaceAll('set CLASSPATH=.*', Matcher.quoteReplacement( 42 | "set CLASSPATH=%APP_HOME%\\lib\\${pathingJar.archiveName};%APP_HOME%\\lib\\${jar.archiveName}")) 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /gradle/protobuf.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | */ 11 | plugins.withId('com.google.protobuf') { 12 | protobuf { 13 | protoc { 14 | artifact = "com.google.protobuf:protoc:${protobufProtocVersion}" 15 | } 16 | plugins { 17 | grpc { 18 | artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" 19 | } 20 | } 21 | generatedFilesBaseDir = "$projectDir/src/generated/grpc-java" 22 | generateProtoTasks { 23 | all()*.plugins { 24 | grpc {} 25 | } 26 | } 27 | } 28 | 29 | clean { 30 | delete protobuf.generatedFilesBaseDir 31 | } 32 | 33 | sourceSets { 34 | main.java.srcDirs "${protobuf.generatedFilesBaseDir}/main/java" 35 | main.java.srcDirs "${protobuf.generatedFilesBaseDir}/main/grpc" 36 | } 37 | 38 | dependencies { 39 | compile group: 'io.grpc', name: 'grpc-netty', version: grpcVersion 40 | compile group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion 41 | compile group: 'io.grpc', name: 'grpc-stub', version: grpcVersion 42 | } 43 | 44 | idea { 45 | module { 46 | sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java") 47 | sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/grpc") 48 | } 49 | } 50 | 51 | ideaModule.dependsOn(['generateProto', 'generateTestProto']) 52 | eclipseClasspath.dependsOn(['generateProto', 'generateTestProto']) 53 | } -------------------------------------------------------------------------------- /checkstyle/intelij.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 14 | 15 | 26 | 27 | 38 | -------------------------------------------------------------------------------- /serializers/json/src/main/java/io/pravega/schemaregistry/serializer/json/impl/JsonSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.impl; 11 | 12 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 13 | import com.fasterxml.jackson.annotation.PropertyAccessor; 14 | import com.fasterxml.jackson.databind.ObjectMapper; 15 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 16 | import io.pravega.schemaregistry.serializer.shared.codec.Encoder; 17 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 18 | import io.pravega.schemaregistry.serializer.json.schemas.JSONSchema; 19 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractSerializer; 20 | 21 | import java.io.IOException; 22 | import java.io.OutputStream; 23 | 24 | public class JsonSerializer extends AbstractSerializer { 25 | private final ObjectMapper objectMapper; 26 | public JsonSerializer(String groupId, SchemaRegistryClient client, JSONSchema schema, 27 | Encoder encoder, boolean registerSchema, boolean encodeHeader) { 28 | super(groupId, client, schema, encoder, registerSchema, encodeHeader); 29 | objectMapper = new ObjectMapper(); 30 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 31 | } 32 | 33 | @Override 34 | protected void serialize(T var, SchemaInfo schemaInfo, OutputStream outputStream) throws IOException { 35 | objectMapper.writeValue(outputStream, var); 36 | outputStream.flush(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /checkstyle/import-control.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /server/src/test/java/io/pravega/schemaregistry/pravegastandalone/PravegaStandaloneUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.pravegastandalone; 11 | 12 | import io.pravega.local.LocalPravegaEmulator; 13 | import lombok.SneakyThrows; 14 | import lombok.Synchronized; 15 | 16 | import java.util.concurrent.atomic.AtomicReference; 17 | 18 | public class PravegaStandaloneUtils { 19 | private static final AtomicReference SINGLETON = new AtomicReference<>(); 20 | private final LocalPravegaEmulator localPravega; 21 | 22 | @SneakyThrows 23 | private PravegaStandaloneUtils() { 24 | LocalPravegaEmulator.LocalPravegaEmulatorBuilder emulatorBuilder = LocalPravegaEmulator 25 | .builder() 26 | .controllerPort(9090) 27 | .segmentStorePort(1234) 28 | .zkPort(2180) 29 | .restServerPort(9091) 30 | .enableRestServer(false) 31 | .enableAuth(false) 32 | .enableTls(false); 33 | 34 | localPravega = emulatorBuilder.build(); 35 | localPravega.getInProcPravegaCluster().start(); 36 | } 37 | 38 | @Synchronized 39 | public static PravegaStandaloneUtils startPravega() { 40 | if (SINGLETON.get() == null) { 41 | SINGLETON.set(new PravegaStandaloneUtils()); 42 | } 43 | return SINGLETON.get(); 44 | } 45 | 46 | public String getControllerURI() { 47 | return localPravega.getInProcPravegaCluster().getControllerURI(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /charts/schema-registry/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | 12 | 13 | {{/* vim: set filetype=mustache: */}} 14 | {{/* 15 | Expand the name of the chart. 16 | */}} 17 | {{- define "schema-registry.name" -}} 18 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 19 | {{- end }} 20 | 21 | {{/* 22 | Create a default fully qualified app name. 23 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 24 | If release name contains chart name it will be used as a full name. 25 | */}} 26 | {{- define "schema-registry.fullname" -}} 27 | {{- if .Values.fullnameOverride -}} 28 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 29 | {{- else -}} 30 | {{- $name := default .Chart.Name .Values.nameOverride -}} 31 | {{- if contains $name .Release.Name -}} 32 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 33 | {{- else -}} 34 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 35 | {{- end -}} 36 | {{- end -}} 37 | {{- end -}} 38 | 39 | {{/* 40 | Common labels 41 | */}} 42 | {{- define "schema-registry.commonLabels" -}} 43 | {{ include "schema-registry.selectorLabels" . }} 44 | {{- if .Chart.AppVersion }} 45 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 46 | {{- end }} 47 | app.kubernetes.io/managed-by: {{ .Release.Service }} 48 | helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 49 | {{- end -}} 50 | 51 | {{/* 52 | Selector labels 53 | */}} 54 | {{- define "schema-registry.selectorLabels" -}} 55 | app.kubernetes.io/name: {{ include "schema-registry.name" . }} 56 | {{- end }} 57 | -------------------------------------------------------------------------------- /serializers/src/main/java/io/pravega/schemaregistry/serializers/MultipleFormatSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializers; 11 | 12 | import io.pravega.client.stream.Serializer; 13 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 14 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractSerializer; 15 | import org.apache.commons.lang3.NotImplementedException; 16 | 17 | import java.nio.ByteBuffer; 18 | import java.util.concurrent.ConcurrentHashMap; 19 | import java.util.function.Function; 20 | 21 | class MultipleFormatSerializer implements Serializer> { 22 | private final Function> serializerFunction; 23 | 24 | private final ConcurrentHashMap> serializersMap; 25 | 26 | MultipleFormatSerializer(Function> serializerFunction) { 27 | this.serializerFunction = serializerFunction; 28 | this.serializersMap = new ConcurrentHashMap<>(); 29 | } 30 | 31 | @Override 32 | public ByteBuffer serialize(WithSchema value) { 33 | AbstractSerializer serializer = serializersMap.computeIfAbsent(value.getSchema().getSchemaInfo(), 34 | x -> serializerFunction.apply(value.getSchema().getSchemaInfo())); 35 | return serializer.serialize(value.getObject()); 36 | } 37 | 38 | @Override 39 | public WithSchema deserialize(ByteBuffer serializedValue) { 40 | throw new NotImplementedException("Deserializer not implemented"); 41 | } 42 | } -------------------------------------------------------------------------------- /serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/SchemaDefinitions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.avro.testobjs; 11 | 12 | import org.apache.avro.Schema; 13 | import org.apache.avro.SchemaBuilder; 14 | 15 | public class SchemaDefinitions { 16 | public static final Schema ENUM = SchemaBuilder 17 | .enumeration("a").symbols("a", "b", "c"); 18 | 19 | public static final Schema SCHEMA1 = SchemaBuilder 20 | .record("MyTest") 21 | .fields() 22 | .name("a") 23 | .type(Schema.create(Schema.Type.STRING)) 24 | .noDefault() 25 | .endRecord(); 26 | 27 | public static final Schema SCHEMA2 = SchemaBuilder 28 | .record("MyTest") 29 | .fields() 30 | .name("a") 31 | .type(Schema.create(Schema.Type.STRING)) 32 | .noDefault() 33 | .name("b") 34 | .type(Schema.create(Schema.Type.STRING)) 35 | .withDefault("backwardPolicy compatible with schema1") 36 | .endRecord(); 37 | 38 | public static final Schema SCHEMA3 = SchemaBuilder 39 | .record("MyTest") 40 | .fields() 41 | .name("a") 42 | .type(Schema.create(Schema.Type.STRING)) 43 | .noDefault() 44 | .name("b") 45 | .type(Schema.create(Schema.Type.STRING)) 46 | .noDefault() 47 | .name("c") 48 | .type(Schema.create(Schema.Type.STRING)) 49 | .noDefault() 50 | .endRecord(); 51 | } 52 | -------------------------------------------------------------------------------- /auth/src/main/java/io/pravega/schemaregistry/common/AuthHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import com.google.common.base.Preconditions; 13 | import com.google.common.base.Strings; 14 | import io.pravega.auth.AuthenticationException; 15 | 16 | public class AuthHelper { 17 | /** 18 | * Encodes auth method and auth token with as whitespace separated string. 19 | * 20 | * @param method Auth method. 21 | * @param token Auth token. 22 | * @return Encoded method and token. 23 | */ 24 | public static String getAuthorizationHeader(String method, String token) { 25 | Preconditions.checkArgument(!Strings.isNullOrEmpty(method)); 26 | Preconditions.checkArgument(!Strings.isNullOrEmpty(token)); 27 | return String.format("%s %s", method, token); 28 | } 29 | 30 | /** 31 | * Extracts method and token from credentials created using {@link AuthHelper#getAuthorizationHeader(String, String)}. 32 | * 33 | * @param credentials credentials 34 | * @return Array of method and token. 35 | * @throws AuthenticationException throws authentication exception for malformed credentials. 36 | */ 37 | public static String[] extractMethodAndToken(String credentials) throws AuthenticationException { 38 | Preconditions.checkNotNull(credentials, "Credentials cannot be null"); 39 | String[] parts = credentials.split("\\s+", 2); 40 | if (parts.length != 2) { 41 | throw new AuthenticationException("Malformed request"); 42 | } 43 | return parts; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /server/src/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | schema-registry.log 14 | 15 | 17 | schema_registry_%d{yyyy-MM-dd}.%i.log.gz 18 | 19 | 20 | 10MB 21 | 22 | 23 | 30 24 | 25 | 26 | 27 | UTF-8 28 | %d %-4relative [%thread] %-5level %logger{35} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | UTF-8 35 | %d %-4relative [%thread] %-5level %logger{35} - %msg%n 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /server/src/test/java/io/pravega/schemaregistry/server/rest/ConfigTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest; 11 | 12 | import io.pravega.test.common.AssertExtensions; 13 | import org.junit.Test; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertFalse; 17 | import static org.junit.Assert.assertTrue; 18 | 19 | public class ConfigTest { 20 | @Test 21 | public void testValidConfig() { 22 | ServiceConfig config = ServiceConfig.builder().build(); 23 | assertEquals(config.getHost(), "0.0.0.0"); 24 | assertEquals(config.getPort(), 9092); 25 | assertFalse(config.isAuthEnabled()); 26 | assertFalse(config.isTlsEnabled()); 27 | } 28 | 29 | @Test 30 | public void testTlsConfig() { 31 | // invalid config 32 | AssertExtensions.assertThrows(IllegalArgumentException.class, () -> ServiceConfig.builder().tlsEnabled(true).build()); 33 | AssertExtensions.assertThrows(IllegalArgumentException.class, () -> ServiceConfig.builder().tlsEnabled(true) 34 | .tlsCertFilePath("a").build()); 35 | AssertExtensions.assertThrows(IllegalArgumentException.class, () -> 36 | ServiceConfig.builder().tlsEnabled(true).tlsCertFilePath("a").tlsKeyStoreFilePath("a").build()); 37 | 38 | // valid config 39 | ServiceConfig config = ServiceConfig.builder().tlsEnabled(true).tlsCertFilePath("a").tlsKeyStoreFilePath("a").tlsKeyStorePasswordFilePath("a").build(); 40 | assertTrue(config.isTlsEnabled()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /serializers/json/src/main/java/io/pravega/schemaregistry/serializer/json/impl/JsonGenericDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.impl; 11 | 12 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 13 | import com.fasterxml.jackson.annotation.PropertyAccessor; 14 | import com.fasterxml.jackson.databind.JsonNode; 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 17 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 18 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 19 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 20 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | public class JsonGenericDeserializer extends AbstractDeserializer { 26 | private final ObjectMapper objectMapper; 27 | 28 | public JsonGenericDeserializer(String groupId, SchemaRegistryClient client, 29 | SerializerConfig.Decoders decoders, EncodingCache encodingCache, boolean encodeHeader) { 30 | super(groupId, client, null, false, decoders, encodingCache, encodeHeader); 31 | this.objectMapper = new ObjectMapper(); 32 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 33 | } 34 | 35 | @Override 36 | public final JsonNode deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { 37 | return objectMapper.readTree(inputStream); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | 11 | dockerExecutable=/usr/bin/docker 12 | 13 | #3rd party Versions 14 | apacheCommonsCsvVersion=1.5 15 | apacheCommonsCompressVersion=1.21 16 | checkstyleToolVersion=10.12.3 17 | commonsBeanutilsVersion=1.9.4 18 | commonsioVersion=2.11.0 19 | commonsLang3Version=3.7 20 | dockerClientVersion=8.16.0 21 | spotbugsVersion=4.0.6 22 | spotbugsAnnotationsVersion=4.0.6 23 | spotbugsPluginVersion=4.4.4 24 | gradleDockerPlugin=3.1.0 25 | gradleLombokPluginVersion=4.0.0 26 | gradleSshPluginVersion=2.9.0 27 | guavaVersion=32.0.1-jre 28 | javaxServletApiVersion=4.0.0 29 | jacksonVersion=2.14.1 30 | everitVersion=1.14.3 31 | javaxwsrsApiVersion=2.1 32 | jaxbVersion=2.3.1 33 | javaxAnnotationVersion=1.3.2 34 | jerseyVersion=2.35 35 | junitVersion=4.13.2 36 | lombokVersion=1.18.12 37 | mockitoVersion=3.3.3 38 | nettyBoringSSLVersion=2.0.54.Final 39 | jacocoVersion=0.8.5 40 | protobufGradlePlugin=0.8.15 41 | protobufProtocVersion=3.21.7 42 | protobufUtilVersion=3.24.3 43 | qosLogbackVersion=1.2.13 44 | shadowGradlePlugin=4.0.2 45 | swaggerJersey2JaxrsVersion=1.6.11 46 | slf4jApiVersion=1.7.25 47 | gradleGitPluginVersion=4.1.1 48 | avroVersion=1.11.3 49 | avroProtobufVersion=1.10.2 50 | snappyVersion=1.1.7.3 51 | javaxActivationVersion=1.1.1 52 | pravegaVersion=0.13.0 53 | pravegaKeyCloakVersion=0.13.0 54 | apacheZookeeperVersion=3.6.3 55 | snakeYamlVersion=2.0 56 | 57 | # Version and base tags can be overridden at build time 58 | schemaregistryVersion=0.7.0-SNAPSHOT 59 | schemaregistryBaseTag=pravega/schemaregistry 60 | 61 | # Pravega Signing Key 62 | signing.keyId= 63 | # This will be defaulted to ~/.gnupg/secring.gpg if not provided as a command line property 64 | signing.secretKeyRingFile= 65 | -------------------------------------------------------------------------------- /common/src/test/java/io/pravega/schemaregistry/common/ContinuationTokenIteratorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import com.google.common.collect.Lists; 13 | import lombok.Data; 14 | import org.junit.Test; 15 | 16 | import java.util.AbstractMap; 17 | import java.util.Collection; 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.Queue; 22 | import java.util.concurrent.LinkedBlockingQueue; 23 | import java.util.function.Function; 24 | 25 | import static org.junit.Assert.*; 26 | import static org.mockito.Mockito.*; 27 | 28 | public class ContinuationTokenIteratorTest { 29 | @Test 30 | public void test() { 31 | Queue responses = spy(new LinkedBlockingQueue<>()); 32 | responses.add(new ListWithToken(Lists.newArrayList(1, 2, 3, 4, 5), "1")); 33 | responses.add(new ListWithToken(Collections.emptyList(), "")); 34 | Function>> func = token -> { 35 | ListWithToken result = responses.poll(); 36 | return new AbstractMap.SimpleEntry<>(result.token, result.list); 37 | }; 38 | ContinuationTokenIterator myIterator = new ContinuationTokenIterator<>(func, null); 39 | for (int i = 0; i < 5; i++) { 40 | assertTrue(myIterator.hasNext()); 41 | assertEquals(myIterator.next().intValue(), i + 1); 42 | } 43 | verify(responses, times(1)).poll(); 44 | assertFalse(myIterator.hasNext()); 45 | } 46 | 47 | @Data 48 | static class ListWithToken { 49 | private final List list; 50 | private final String token; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /serializers/src/main/java/io/pravega/schemaregistry/serializers/JsonWithSchemaDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializers; 11 | 12 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 13 | import com.fasterxml.jackson.annotation.PropertyAccessor; 14 | import com.fasterxml.jackson.databind.JsonNode; 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 17 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 18 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 19 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 20 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | class JsonWithSchemaDeserializer extends AbstractDeserializer> { 26 | private final ObjectMapper objectMapper; 27 | 28 | JsonWithSchemaDeserializer(String groupId, SchemaRegistryClient client, 29 | SerializerConfig.Decoders decoders, EncodingCache encodingCache, boolean encodeHeader) { 30 | super(groupId, client, null, false, decoders, encodingCache, encodeHeader); 31 | this.objectMapper = new ObjectMapper(); 32 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 33 | } 34 | 35 | @Override 36 | public final WithSchema deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { 37 | JsonNode obj = objectMapper.readTree(inputStream); 38 | return new WithSchema<>(writerSchemaInfo, obj, (x, y) -> (JsonNode) y); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/rules/CompatibilityChecker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.rules; 11 | 12 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * BackwardAndForward checker interface to compare a schema against existing schemas for compatibility. 18 | */ 19 | public interface CompatibilityChecker { 20 | /** 21 | * Checks if readUsing can be used to read data written using all schemas in writtenUsing. 22 | * 23 | * @param readUsing Schema used while reading the data. 24 | * @param writtenUsing Schema used for writing the data. 25 | * @return True if readUsing can be used to read data written using writtenUsing, false otherwise. 26 | */ 27 | boolean canRead(SchemaInfo readUsing, List writtenUsing); 28 | 29 | /** 30 | * Checks if all schemas in readUsing can be used to read data written using writtenUsing. 31 | * 32 | * @param writtenUsing Schema used for writing the data. 33 | * @param readUsing Schema used while reading the data. 34 | * @return True if any of readUsing can be used to read data written using writtenUsing, false otherwise. 35 | */ 36 | boolean canBeRead(SchemaInfo writtenUsing, List readUsing); 37 | 38 | /** 39 | * Checks if both schema and schemaList can be used to read data written with either. 40 | * 41 | * @param schema Schema to check. 42 | * @param schemaList All schemas to check against. 43 | * @return True if schema can read and be readby all schemas in the schemas, false otherwise. 44 | */ 45 | boolean canMutuallyRead(SchemaInfo schema, List schemaList); 46 | } 47 | -------------------------------------------------------------------------------- /checkstyle/spotbugs-include.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /common/src/test/java/io/pravega/schemaregistry/common/ChunkUtilTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import io.pravega.common.util.ByteArraySegment; 13 | import org.junit.Test; 14 | 15 | import java.nio.ByteBuffer; 16 | import java.util.List; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | 20 | public class ChunkUtilTest { 21 | @Test 22 | public void chunkTest() { 23 | List sc = ChunkUtil.chunk(ByteBuffer.wrap(new byte[100]), 900 * 1024); 24 | assertEquals(sc.size(), 1); 25 | assertEquals(sc.get(0).getLength(), 100); 26 | 27 | sc = ChunkUtil.chunk(ByteBuffer.wrap(new byte[0]), 900 * 1024); 28 | assertEquals(sc.size(), 1); 29 | assertEquals(sc.get(0).getLength(), 0); 30 | 31 | // schema data = 900 kb. it should still result in a single chunk 32 | sc = ChunkUtil.chunk(ByteBuffer.wrap(new byte[900 * 1024]), 900 * 1024); 33 | assertEquals(sc.size(), 1); 34 | assertEquals(sc.get(0).getLength(), 900 * 1024); 35 | 36 | // schema data 1mb > 900 kb. it should result in 2 chunks. 37 | sc = ChunkUtil.chunk(ByteBuffer.wrap(new byte[1024 * 1024]), 900 * 1024); 38 | assertEquals(sc.size(), 2); 39 | assertEquals(sc.get(0).getLength(), 900 * 1024); 40 | assertEquals(sc.get(1).getLength(), 124 * 1024); 41 | 42 | // schema data 2700kb > 900 kb. it should result in 3 chunks. 43 | sc = ChunkUtil.chunk(ByteBuffer.wrap(new byte[3 * 900 * 1024]), 900 * 1024); 44 | assertEquals(sc.size(), 3); 45 | assertEquals(sc.get(0).getLength(), 900 * 1024); 46 | assertEquals(sc.get(1).getLength(), 900 * 1024); 47 | assertEquals(sc.get(2).getLength(), 900 * 1024); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /serializers/avro/src/test/resources/avro/user.avsc: -------------------------------------------------------------------------------- 1 | { 2 | "type": "record", 3 | "namespace": "io.openmessaging.benchmark.driver.pravega.schema.generated.avro", 4 | "name": "User", 5 | "fields": [ 6 | { 7 | "name": "userId", 8 | "type": "string" 9 | }, 10 | { 11 | "name": "name", 12 | "type": "string" 13 | }, 14 | { 15 | "name": "biography", 16 | "type": ["null", "string"], 17 | "default": null 18 | }, 19 | { 20 | "name": "eventTimestamp", 21 | "type": ["null", "long"], 22 | "default": null 23 | }, 24 | { 25 | "name": "keyValues", 26 | "type": ["null", { 27 | "type": "array", 28 | "items": { 29 | "name": "KeyValue", 30 | "type": "record", 31 | "fields": [ 32 | {"name":"name", "type":"string"}, 33 | {"name":"value", "type":"string"} 34 | ] 35 | } 36 | }] 37 | }, 38 | { 39 | "name": "keyValues2", 40 | "type": ["null", { 41 | "type": "array", 42 | "items": { 43 | "name": "KeyValue2", 44 | "type": "record", 45 | "fields": [ 46 | {"name":"name", "type":"string"}, 47 | {"name":"value", "type":"string"} 48 | ] 49 | } 50 | }] 51 | }, 52 | { 53 | "name": "keyValues3", 54 | "type": ["null", { 55 | "type": "array", 56 | "items": { 57 | "name": "KeyValue3", 58 | "type": "record", 59 | "fields": [ 60 | {"name":"name", "type":"string"}, 61 | {"name":"value", "type":"string"} 62 | ] 63 | } 64 | }] 65 | }, 66 | { 67 | "name": "address", 68 | "type": { 69 | "name" : "AddressEntry", 70 | "type" : "record", 71 | "fields": [ 72 | { 73 | "name": "streetAddress", 74 | "type": "string" 75 | }, 76 | { 77 | "name": "postalCode", 78 | "type": ["null", "int"], 79 | "default": null 80 | }, 81 | { 82 | "name": "city", 83 | "type": "string" 84 | } 85 | ] 86 | } 87 | } 88 | ] 89 | } -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/credentials/PravegaCredentialProvider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.credentials; 11 | 12 | import io.pravega.client.ClientConfig; 13 | import io.pravega.schemaregistry.common.CredentialProvider; 14 | import io.pravega.shared.security.auth.Credentials; 15 | 16 | /** 17 | * Credential provider that is a wrapper over and uses pravega credentials to authenticate to schema registry. 18 | * This is to be used if users want to use the same credentials to authenticate to schema registry 19 | * that they have used in pravega client. 20 | * This can be achieved in one of two ways - 21 | * 1. instantiate this class with Pravega client config and this will extract credentials from the client config. 22 | * 2. instantiate this class without any credentials and it will extract credentials from the environment 23 | * by creating a default clientconfig which loads the credentials from the environment variables or system properies. 24 | * Refer to {@link ClientConfig} to see how credentials are loaded from the environment. 25 | */ 26 | public class PravegaCredentialProvider implements CredentialProvider { 27 | private final Credentials credentials; 28 | 29 | public PravegaCredentialProvider(ClientConfig pravegaClientConfig) { 30 | this.credentials = pravegaClientConfig.getCredentials(); 31 | } 32 | 33 | public PravegaCredentialProvider() { 34 | credentials = ClientConfig.builder().build().getCredentials(); 35 | } 36 | 37 | @Override 38 | public String getMethod() { 39 | return credentials.getAuthenticationType(); 40 | } 41 | 42 | @Override 43 | public String getToken() { 44 | return credentials.getAuthenticationToken(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/GroupHistoryRecord.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import lombok.Data; 13 | import lombok.NonNull; 14 | 15 | /** 16 | * Describes changes to the group and the compatibility {@link GroupHistoryRecord#compatibility} that were 17 | * applied while registering {@link GroupHistoryRecord#schemaInfo} and the unique {@link GroupHistoryRecord#versionInfo} identifier 18 | * that was assigned to it. 19 | * It also has {@link GroupHistoryRecord#timestamp} when the schemaInfo was added and includes an optional 20 | * {@link GroupHistoryRecord#schemaString} which is populated only if serialization format is one of {@link SerializationFormat#Avro} 21 | * {@link SerializationFormat#Json} or {@link SerializationFormat#Protobuf}. This string is just to help make the schemaInfo human readable. 22 | */ 23 | @Data 24 | public class GroupHistoryRecord { 25 | /** 26 | * Schema information object for the schemaInfo that was added to the group. 27 | */ 28 | private @NonNull final SchemaInfo schemaInfo; 29 | /** 30 | * Version information object that uniquely identifies the schemaInfo in the group. 31 | */ 32 | private @NonNull final VersionInfo versionInfo; 33 | /** 34 | * Compatibility applied at the time when the schemaInfo was registered. 35 | */ 36 | private @NonNull final Compatibility compatibility; 37 | /** 38 | * Service's Time when the schemaInfo was registered. 39 | */ 40 | private final long timestamp; 41 | /** 42 | * A json format string representing the schemaInfo. This string will be populated only for serialization formats 43 | * that the service can parse. 44 | */ 45 | private final String schemaString; 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /serializers/json/src/main/java/io/pravega/schemaregistry/serializer/json/impl/JsonStringDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.impl; 11 | 12 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 13 | import com.fasterxml.jackson.annotation.PropertyAccessor; 14 | import com.fasterxml.jackson.databind.ObjectMapper; 15 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 16 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 17 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 18 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 19 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | 24 | class JsonStringDeserializer extends AbstractDeserializer { 25 | private final ObjectMapper objectMapper; 26 | 27 | JsonStringDeserializer(String groupId, SchemaRegistryClient client, 28 | SerializerConfig.Decoders decoders, EncodingCache encodingCache, boolean encodeHeader) { 29 | super(groupId, client, null, false, decoders, encodingCache, encodeHeader); 30 | this.objectMapper = new ObjectMapper(); 31 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 32 | objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); 33 | objectMapper.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY); 34 | } 35 | 36 | @Override 37 | public final String deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { 38 | Object obj = objectMapper.readValue(inputStream, Object.class); 39 | return objectMapper.writeValueAsString(obj); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /serializers/protobuf/src/main/java/io/pravega/schemaregistry/serializer/protobuf/impl/ProtobufDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.protobuf.impl; 11 | 12 | import com.google.common.base.Preconditions; 13 | import com.google.protobuf.GeneratedMessageV3; 14 | import com.google.protobuf.InvalidProtocolBufferException; 15 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 16 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 17 | import io.pravega.schemaregistry.serializer.protobuf.schemas.ProtobufSchema; 18 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 19 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 20 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | public class ProtobufDeserializer extends AbstractDeserializer { 26 | private final ProtobufSchema protobufSchema; 27 | ProtobufDeserializer(String groupId, SchemaRegistryClient client, 28 | ProtobufSchema schema, SerializerConfig.Decoders decoder, 29 | EncodingCache encodingCache, boolean encodeHeader) { 30 | super(groupId, client, schema, true, decoder, encodingCache, encodeHeader); 31 | Preconditions.checkNotNull(schema); 32 | this.protobufSchema = schema; 33 | } 34 | 35 | @Override 36 | public final T deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { 37 | try { 38 | return protobufSchema.getParser().parseFrom(inputStream); 39 | } catch (InvalidProtocolBufferException e) { 40 | throw new IOException("Invalid protobuffer serialized bytes", e); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/MultiplexedDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import com.google.common.base.Preconditions; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 15 | import org.apache.commons.lang3.SerializationException; 16 | 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.util.Map; 20 | 21 | /** 22 | * Deserializer which multiplexes for multiple object types. Based on the supplied object, it invokes the 23 | * deserializer for that object type. 24 | * 25 | * @param Type of object. 26 | */ 27 | public class MultiplexedDeserializer extends AbstractDeserializer { 28 | private final Map> deserializers; 29 | 30 | public MultiplexedDeserializer(String groupId, SchemaRegistryClient client, 31 | Map> deserializers, 32 | SerializerConfig.Decoders decoders, 33 | EncodingCache encodingCache) { 34 | super(groupId, client, null, false, decoders, encodingCache, true); 35 | this.deserializers = deserializers; 36 | } 37 | 38 | @Override 39 | public final T deserialize(InputStream inputStream, SchemaInfo writerSchema, SchemaInfo readerSchema) throws IOException { 40 | Preconditions.checkNotNull(writerSchema); 41 | AbstractDeserializer deserializer = deserializers.get(writerSchema.getType()); 42 | if (deserializer == null) { 43 | throw new SerializationException("deserializer not supplied for type " + writerSchema.getType()); 44 | } 45 | return deserializer.deserialize(inputStream, writerSchema, readerSchema); 46 | } 47 | } -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/group/records/EncodingIdSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.group.records; 11 | 12 | import io.pravega.common.io.serialization.RevisionDataInput; 13 | import io.pravega.common.io.serialization.RevisionDataOutput; 14 | import io.pravega.common.io.serialization.VersionedSerializer; 15 | import io.pravega.schemaregistry.contract.data.EncodingId; 16 | import io.pravega.schemaregistry.contract.data.EncodingInfo; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Encoding Id generated by registry service for each unique combination of schema version and codec type. 22 | * The encoding id will typically be attached to the encoded data in a header to describe how to from the following data. 23 | * The registry service exposes APIs to resolve encoding id to {@link EncodingInfo} objects that include details about the 24 | * encoding used. 25 | */ 26 | public class EncodingIdSerializer extends VersionedSerializer.WithBuilder { 27 | public static final EncodingIdSerializer SERIALIZER = new EncodingIdSerializer(); 28 | 29 | @Override 30 | protected EncodingId.EncodingIdBuilder newBuilder() { 31 | return EncodingId.builder(); 32 | } 33 | 34 | @Override 35 | protected byte getWriteVersion() { 36 | return 0; 37 | } 38 | 39 | @Override 40 | protected void declareVersions() { 41 | version(0).revision(0, this::write00, this::read00); 42 | } 43 | 44 | private void write00(EncodingId e, RevisionDataOutput target) throws IOException { 45 | target.writeInt(e.getId()); 46 | } 47 | 48 | private void read00(RevisionDataInput source, EncodingId.EncodingIdBuilder b) throws IOException { 49 | b.id(source.readInt()); 50 | } 51 | } -------------------------------------------------------------------------------- /serializers/json/src/main/java/io/pravega/schemaregistry/serializer/json/impl/JsonDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.impl; 11 | 12 | import com.fasterxml.jackson.annotation.PropertyAccessor; 13 | import com.fasterxml.jackson.databind.ObjectMapper; 14 | import com.google.common.base.Preconditions; 15 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 16 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 17 | import io.pravega.schemaregistry.serializer.json.schemas.JSONSchema; 18 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 19 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 20 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 26 | 27 | public class JsonDeserializer extends AbstractDeserializer { 28 | private final JSONSchema jsonSchema; 29 | private final ObjectMapper objectMapper; 30 | 31 | public JsonDeserializer(String groupId, SchemaRegistryClient client, 32 | JSONSchema schema, 33 | SerializerConfig.Decoders decoders, EncodingCache encodingCache, boolean encodeHeader) { 34 | super(groupId, client, schema, true, decoders, encodingCache, encodeHeader); 35 | Preconditions.checkNotNull(schema); 36 | this.jsonSchema = schema; 37 | this.objectMapper = new ObjectMapper(); 38 | objectMapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY); 39 | } 40 | 41 | @Override 42 | public final T deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { 43 | return objectMapper.readValue(inputStream, jsonSchema.getDerived()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/group/GroupTable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.group; 11 | 12 | import io.pravega.schemaregistry.storage.Etag; 13 | import lombok.Data; 14 | 15 | import java.util.List; 16 | import java.util.concurrent.CompletableFuture; 17 | import java.util.function.Predicate; 18 | 19 | import static io.pravega.schemaregistry.storage.impl.group.records.TableRecords.*; 20 | 21 | /** 22 | * Table for storing group metadata. 23 | * @param Version Type 24 | */ 25 | public interface GroupTable { 26 | CompletableFuture addEntry(TableKey key, TableValue value); 27 | 28 | CompletableFuture updateEntry(TableKey key, TableValue value, V version); 29 | 30 | CompletableFuture updateEntries(List> entries); 31 | 32 | CompletableFuture getEntry(TableKey key, Class tClass); 33 | 34 | CompletableFuture> getEntryWithVersion(TableKey key, Class tClass); 35 | 36 | CompletableFuture> getEntries(List keys, Class tClass); 37 | 38 | CompletableFuture>> getEntriesWithVersion(List keys, Class tClass); 39 | 40 | CompletableFuture> getAllKeys(); 41 | 42 | CompletableFuture>> getAllEntries(); 43 | 44 | CompletableFuture>> getAllEntries(Predicate filterKeys); 45 | 46 | Etag toEtag(V version); 47 | 48 | V fromEtag(Etag etag); 49 | 50 | @Data 51 | class Value { 52 | private final T value; 53 | private final V version; 54 | } 55 | 56 | @Data 57 | class Entry { 58 | private final TableKey key; 59 | private final TableValue value; 60 | private final V version; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/src/test/java/io/pravega/schemaregistry/integrationtest/TestEndToEndWithFailingAuth.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.integrationtest; 11 | 12 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClientConfig; 14 | import io.pravega.schemaregistry.client.SchemaRegistryClientFactory; 15 | import io.pravega.schemaregistry.client.exceptions.RegistryExceptions; 16 | import io.pravega.schemaregistry.common.CredentialProvider; 17 | import io.pravega.test.common.AssertExtensions; 18 | import lombok.extern.slf4j.Slf4j; 19 | import org.apache.curator.shaded.com.google.common.base.Charsets; 20 | import org.junit.Test; 21 | 22 | import java.net.URI; 23 | import java.util.Base64; 24 | 25 | @Slf4j 26 | public class TestEndToEndWithFailingAuth extends TestEndToEndWithAuth { 27 | @Override 28 | public SchemaRegistryClient newClient() { 29 | return SchemaRegistryClientFactory.withDefaultNamespace( 30 | SchemaRegistryClientConfig.builder().schemaRegistryUri(URI.create("http://localhost:" + port)) 31 | .authentication(new CredentialProvider.DefaultCredentialProvider("Basic", 32 | Base64.getEncoder().encodeToString(("a" + ":" + "b").getBytes(Charsets.UTF_8)))) 33 | .build()); 34 | } 35 | 36 | @Override 37 | @Test 38 | public void testEndToEnd() { 39 | AssertExtensions.assertThrows("expected unauthorized exception", super::testEndToEnd, 40 | e -> e instanceof RegistryExceptions.UnauthorizedException); 41 | } 42 | 43 | @Override 44 | @Test 45 | public void testLargeSchemas() { 46 | AssertExtensions.assertThrows("expected unauthorized exception", super::testLargeSchemas, 47 | e -> e instanceof RegistryExceptions.UnauthorizedException); 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/group/records/VersionInfoSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.group.records; 11 | 12 | import io.pravega.common.io.serialization.RevisionDataInput; 13 | import io.pravega.common.io.serialization.RevisionDataOutput; 14 | import io.pravega.common.io.serialization.VersionedSerializer; 15 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 16 | import io.pravega.schemaregistry.contract.data.VersionInfo; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Object that captures the version of a schema within a group. 22 | * It contains type matching {@link SchemaInfo#getType()} along with the registry assigned version for the schema in 23 | * the group. 24 | */ 25 | public class VersionInfoSerializer extends VersionedSerializer.WithBuilder { 26 | public static final VersionInfoSerializer SERIALIZER = new VersionInfoSerializer(); 27 | 28 | @Override 29 | protected VersionInfo.VersionInfoBuilder newBuilder() { 30 | return VersionInfo.builder(); 31 | } 32 | 33 | @Override 34 | protected byte getWriteVersion() { 35 | return 0; 36 | } 37 | 38 | @Override 39 | protected void declareVersions() { 40 | version(0).revision(0, this::write00, this::read00); 41 | } 42 | 43 | private void write00(VersionInfo e, RevisionDataOutput target) throws IOException { 44 | target.writeUTF(e.getType()); 45 | target.writeUTF(e.getSerializationFormatName()); 46 | target.writeInt(e.getVersion()); 47 | target.writeInt(e.getId()); 48 | } 49 | 50 | private void read00(RevisionDataInput source, VersionInfo.VersionInfoBuilder b) throws IOException { 51 | b.type(source.readUTF()) 52 | .serializationFormatName(source.readUTF()) 53 | .version(source.readInt()) 54 | .id(source.readInt()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/MultiplexedAndGenericDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import com.google.common.base.Preconditions; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.common.Either; 15 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 16 | 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.util.Map; 20 | 21 | public class MultiplexedAndGenericDeserializer extends AbstractDeserializer> { 22 | private final Map> deserializers; 23 | private final AbstractDeserializer genericDeserializer; 24 | 25 | public MultiplexedAndGenericDeserializer(String groupId, SchemaRegistryClient client, 26 | Map> deserializers, 27 | AbstractDeserializer genericDeserializer, 28 | SerializerConfig.Decoders decoders, 29 | EncodingCache encodingCache) { 30 | super(groupId, client, null, false, decoders, encodingCache, true); 31 | this.deserializers = deserializers; 32 | this.genericDeserializer = genericDeserializer; 33 | } 34 | 35 | @Override 36 | public final Either deserialize(InputStream inputStream, SchemaInfo writerSchema, SchemaInfo readerSchema) throws IOException { 37 | Preconditions.checkNotNull(writerSchema); 38 | AbstractDeserializer deserializer = deserializers.get(writerSchema.getType()); 39 | if (deserializer == null) { 40 | return Either.right(genericDeserializer.deserialize(inputStream, writerSchema, readerSchema)); 41 | } else { 42 | return Either.left(deserializer.deserialize(inputStream, writerSchema, readerSchema)); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /documentation/src/docs/installation-guide.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | Prepare your environment 13 | Schema Registry uses Pravega to store the schemas durably. Following steps assumes you have pravega deployed and running. 14 | 15 | ### Helm Chart 16 | ----------------------------- 17 | 18 | Schema registry also includes Helm Charts to deploy Schema Registry service on a Kubernetes cluster. 19 | Detailed instructions can be found [here](https://github.com/pravega/schema-registry/blob/master/charts/schema-registry/README.md) 20 | 21 | ``` 22 | helm install charts/schema-registry 23 | ``` 24 | The charts can be configured to change the number of replicas, supply TLS configuration, controller uri and other schema regsitry configurations. 25 | 26 | ### Running Schema Registry Service in standalone mode 27 | ----------------------------- 28 | 29 | You can download released versions of schema registry from the [github release page](https://github.com/pravega/schema-registry/releases). 30 | 31 | Alternatively, you can also clone the master and install and run the Schema Registry Service locally using following commands: 32 | ``` 33 | 1. ./gradlew install 34 | 2. cd server/build/distributions/ 35 | ``` 36 | 37 | It is prerequisite to run pravega, which the schema registry services uses as its durable storage. 38 | However, for testing/demo purposes it is also possible to run schema registry without a pravega deployment too, but it will not provide any durability and all schemas will be lost as soon as the service is stopped. 39 | 40 | After downloading/installing the schema registry, 41 | ``` 42 | 3. uncompress schema-registry-.tar or schema-registry-.zip 43 | 4. cd schema-registry- 44 | 5. change CONTROLLER_URL in conf/schema-registry.config.properties 45 | 6. ./bin/schema-registry 46 | ``` 47 | The above will start the schema registry server listening on port 9092. 48 | 49 | To run schema registry without pravega, in the conf/schema-registry.config.properties change the STORE_TYPE to `InMemory`. 50 | 51 | -------------------------------------------------------------------------------- /serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/schemas/SchemasTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.avro.schemas; 11 | 12 | import io.pravega.schemaregistry.contract.data.SerializationFormat; 13 | import io.pravega.schemaregistry.serializer.avro.testobjs.SchemaDefinitions; 14 | import io.pravega.schemaregistry.serializer.shared.testobjs.User; 15 | import io.pravega.schemaregistry.serializer.avro.testobjs.generated.Test1; 16 | import io.pravega.schemaregistry.serializer.avro.testobjs.generated.Test2; 17 | import org.apache.avro.specific.SpecificRecordBase; 18 | import org.junit.Test; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertNotNull; 22 | 23 | public class SchemasTest { 24 | @Test 25 | public void testAvroSchema() { 26 | AvroSchema schema = AvroSchema.of(SchemaDefinitions.SCHEMA1); 27 | assertNotNull(schema.getSchema()); 28 | assertEquals(schema.getSchemaInfo().getSerializationFormat(), SerializationFormat.Avro); 29 | 30 | AvroSchema schema2 = AvroSchema.of(User.class); 31 | assertNotNull(schema2.getSchema()); 32 | assertEquals(schema2.getSchemaInfo().getSerializationFormat(), SerializationFormat.Avro); 33 | 34 | AvroSchema schema3 = AvroSchema.of(Test1.class); 35 | assertNotNull(schema3.getSchema()); 36 | assertEquals(schema3.getSchemaInfo().getSerializationFormat(), SerializationFormat.Avro); 37 | 38 | AvroSchema schemabase1 = AvroSchema.ofSpecificRecord(Test1.class); 39 | assertNotNull(schemabase1.getSchema()); 40 | assertEquals(schemabase1.getSchemaInfo().getSerializationFormat(), SerializationFormat.Avro); 41 | 42 | AvroSchema schemabase2 = AvroSchema.ofSpecificRecord(Test2.class); 43 | assertNotNull(schemabase2.getSchema()); 44 | assertEquals(schemabase2.getSchemaInfo().getSerializationFormat(), SerializationFormat.Avro); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/group/records/CompatibilitySerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.group.records; 11 | 12 | import io.pravega.common.io.serialization.RevisionDataInput; 13 | import io.pravega.common.io.serialization.RevisionDataOutput; 14 | import io.pravega.common.io.serialization.VersionedSerializer; 15 | import io.pravega.schemaregistry.contract.data.Compatibility; 16 | 17 | import java.io.IOException; 18 | 19 | public class CompatibilitySerializer extends VersionedSerializer.WithBuilder { 20 | public static final CompatibilitySerializer SERIALIZER = new CompatibilitySerializer(); 21 | 22 | @Override 23 | protected Compatibility.CompatibilityBuilder newBuilder() { 24 | return Compatibility.builder(); 25 | } 26 | 27 | @Override 28 | protected byte getWriteVersion() { 29 | return 0; 30 | } 31 | 32 | 33 | @Override 34 | protected void declareVersions() { 35 | version(0).revision(0, this::write00, this::read00); 36 | } 37 | 38 | private void write00(Compatibility e, RevisionDataOutput target) throws IOException { 39 | target.writeCompactInt(e.getType().ordinal()); 40 | target.writeBoolean(e.getBackwardAndForward() != null); 41 | if (e.getBackwardAndForward() != null) { 42 | BackwardAndForwardSerializer.SERIALIZER.serialize(target, e.getBackwardAndForward()); 43 | } 44 | } 45 | 46 | private void read00(RevisionDataInput source, Compatibility.CompatibilityBuilder b) throws IOException { 47 | int ordinal = source.readCompactInt(); 48 | Compatibility.Type compatibilityType = Compatibility.Type.values()[ordinal]; 49 | b.type(compatibilityType); 50 | boolean backwardAndForwardSpecified = source.readBoolean(); 51 | if (backwardAndForwardSpecified) { 52 | b.backwardAndForward(BackwardAndForwardSerializer.SERIALIZER.deserialize(source)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /serializers/src/main/java/io/pravega/schemaregistry/serializers/MultipleFormatDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializers; 11 | 12 | import com.google.common.base.Preconditions; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 15 | import io.pravega.schemaregistry.contract.data.SerializationFormat; 16 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 17 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 18 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.util.Map; 23 | import java.util.function.BiFunction; 24 | 25 | class MultipleFormatDeserializer extends AbstractDeserializer { 26 | private final Map genericDeserializers; 27 | private final BiFunction transform; 28 | 29 | MultipleFormatDeserializer(String groupId, SchemaRegistryClient client, 30 | Map genericDeserializers, 31 | SerializerConfig.Decoders decoders, 32 | EncodingCache encodingCache, BiFunction transform) { 33 | super(groupId, client, null, false, decoders, encodingCache, true); 34 | this.genericDeserializers = genericDeserializers; 35 | this.transform = transform; 36 | } 37 | 38 | @Override 39 | public final T deserialize(InputStream inputStream, SchemaInfo writerSchema, SchemaInfo readerSchema) throws IOException { 40 | Preconditions.checkNotNull(writerSchema); 41 | return transform.apply(writerSchema.getSerializationFormat(), 42 | genericDeserializers.get(writerSchema.getSerializationFormat()) 43 | .deserialize(inputStream, writerSchema, readerSchema)); 44 | } 45 | } -------------------------------------------------------------------------------- /contract/src/main/swagger/README.md: -------------------------------------------------------------------------------- 1 | 10 | Instructions to generate Server REST API stubs 11 | 12 | ## Delete previously generated directory 13 | ``` 14 | rm -Rf server/src/main/java/io/pravega/schemaregistry/server/io.pravega.rest/generated 15 | ``` 16 | 17 | ## Update schemaregistry.yaml 18 | All REST API modifications should be done by updating the swagger/schemaregistry.yaml specification file. 19 | This can be done manually or by using the online editor at http://editor.swagger.io. 20 | 21 | ## Download Swagger codegen 22 | Download swagger-codegen-cli from maven - http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.3/swagger-codegen-cli-2.2.3.jar 23 | 24 | ## Generate the API stubs using Swagger Codegen 25 | ``` 26 | java -jar swagger-codegen-cli.jar generate -i /contract/src/main/swagger/SchemaRegistry.yaml -l jaxrs -c /contract/src/main/swagger/server.config.json -o /contract/ 27 | ``` 28 | 29 | ## Remove extra files created by codegen 30 | All files that get generated outside of the contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest folder should be deleted and not committed to git. 31 | 32 | ## Update ApiV1.java 33 | The JAXRS API stubs decorated with swagger annotations are generated in .../contract/io/pravega/schemaregistry/contract/v1/ApiV1.java class. 34 | Copy these API descriptions into interfaces in .../contract/io.pravega.schemaregistry/contract//v1/ApiV1.java. 35 | Also make an asynchronour version of APIs in .../contract/io.pravega.schemaregistry/server/rest/v1/ApiV1.java to use only jersey async interfaces. 36 | 37 | ## Generate documentation 38 | ### Download Swagger2Markup CLI 39 | https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup-cli/1.3.3/swagger2markup-cli-1.3.3.jar 40 | 41 | ### Generate and save the markup documentation 42 | ``` 43 | java -Dswagger2markup.markupLanguage=MARKDOWN -Dswagger2markup.generatedExamplesEnabled=true -jar swagger2markup-cli-1.3.3.jar convert -i /contract/src/main/swagger/SchemaRegistry.yaml -f /documentation/src/docs/io.pravega.rest/restapis 44 | ``` 45 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/CodecType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import com.google.common.base.Preconditions; 13 | import com.google.common.collect.ImmutableMap; 14 | import io.pravega.common.ObjectBuilder; 15 | import lombok.Builder; 16 | import lombok.Data; 17 | import lombok.NonNull; 18 | 19 | /** 20 | * Encapsulates properties of a codecType. 21 | */ 22 | @Data 23 | @Builder 24 | public class CodecType { 25 | public static final CodecType NONE = new CodecType(""); 26 | private static final int MAX_PROPERTIES_SIZE = 921600; // 900 kb 27 | 28 | /** 29 | * Name that identifies the codec type. Users could typically use the mime type name for the encoding. 30 | */ 31 | private @NonNull final String name; 32 | /** 33 | * User defined key value strings that users can use to add any additional metadata to the codecType. 34 | * This can be used to share additional information with the decoder about how to decode, for example, if codecType was 35 | * for encryption, the additional information could include algorithm and other params required for decryption. 36 | * This is opaque to the service and stored with the codecType when the codec is registered for a group and delivered 37 | * with encoding information. 38 | */ 39 | private @NonNull final ImmutableMap properties; 40 | 41 | public CodecType(String name) { 42 | this(name, ImmutableMap.of()); 43 | } 44 | 45 | public CodecType(@NonNull String name, @NonNull ImmutableMap properties) { 46 | Preconditions.checkArgument(properties.entrySet().stream().mapToInt(x -> x.getKey().length() + x.getValue().length()) 47 | .reduce(0, Integer::sum) < MAX_PROPERTIES_SIZE, 48 | "Invalid properties, make sure that total size of properties map is less than 900 kb."); 49 | this.name = name; 50 | this.properties = properties; 51 | } 52 | 53 | public static class CodecTypeBuilder implements ObjectBuilder { 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /serializers/src/main/java/io/pravega/schemaregistry/serializers/MultiFormatWithSchemaDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializers; 11 | 12 | import com.google.common.base.Preconditions; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 15 | import io.pravega.schemaregistry.contract.data.SerializationFormat; 16 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; 17 | import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; 18 | import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.util.Map; 23 | import java.util.function.BiFunction; 24 | 25 | class MultiFormatWithSchemaDeserializer extends AbstractDeserializer> { 26 | private final Map genericDeserializers; 27 | private final BiFunction transform; 28 | 29 | MultiFormatWithSchemaDeserializer(String groupId, SchemaRegistryClient client, 30 | Map genericDeserializers, 31 | SerializerConfig.Decoders decoders, 32 | EncodingCache encodingCache, BiFunction transform) { 33 | super(groupId, client, null, false, decoders, encodingCache, true); 34 | this.genericDeserializers = genericDeserializers; 35 | this.transform = transform; 36 | } 37 | 38 | @Override 39 | public final WithSchema deserialize(InputStream inputStream, SchemaInfo writerSchema, SchemaInfo readerSchema) throws IOException { 40 | Preconditions.checkNotNull(writerSchema); 41 | Object obj = genericDeserializers.get(writerSchema.getSerializationFormat()).deserialize(inputStream, writerSchema, readerSchema); 42 | if (obj instanceof WithSchema) { 43 | obj = ((WithSchema) obj).getObject(); 44 | } 45 | return new WithSchema<>(writerSchema, obj, transform); 46 | } 47 | } -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/Forward.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * ForwardPolicy compatibility type which tells the service to check for forwardPolicy compatibilty with latest schema. 25 | */ 26 | @ApiModel(description = "ForwardPolicy compatibility type which tells the service to check for forwardPolicy compatibilty with latest schema.") 27 | 28 | public class Forward { 29 | @JsonProperty("name") 30 | private String name = null; 31 | 32 | public Forward name(String name) { 33 | this.name = name; 34 | return this; 35 | } 36 | 37 | /** 38 | * Get name 39 | * @return name 40 | **/ 41 | @JsonProperty("name") 42 | @ApiModelProperty(required = true, value = "") 43 | @NotNull 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | Forward forward = (Forward) o; 62 | return Objects.equals(this.name, forward.name); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(name); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class Forward {\n"); 75 | 76 | sb.append(" name: ").append(toIndentedString(name)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /server/src/conf/schema-registry.config.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | 11 | ## Instructions for using this file: 12 | # 1. Settings are namespaced. The prefix indicates the component for which the configuration applies. 13 | # 2. All settings have default values hardcoded inside the code. The purpose of this file is to provide Environment Variable 14 | # references so that they may fetch values via such an indirection. 15 | # 3. Each of these settings can be overridden from the command like by specifying a Java System Property. 16 | # Example: setting 'controller.service.port' has a default value of "tcp://localhost:9090", but it can be overridden to a different 17 | # value via the command-line: 18 | # java -Dservice.controller.url="tcp://10.10.10.10:9090" ... 19 | # which will set the value for that setting to "tcp://10.10.10.10:9090", regardless of what this file contains. 20 | 21 | schemaRegistry.store.type.name=${STORE_TYPE} 22 | schemaRegistry.store.pravega.controller.connect.uri=${CONTROLLER_URL} 23 | schemaRegistry.store.pravega.controller.connect.security.tls.trustStore.location=${CONTROLLER_TLS_TRUST_STORE} 24 | schemaRegistry.store.pravega.controller.connect.security.tls.validateHostName.enable=${CONTROLLER_TLS_VALIDATE_HOSTNAME} 25 | schemaRegistry.store.pravega.controller.connect.auth.method=${CONTROLLER_AUTH_METHOD} 26 | schemaRegistry.store.pravega.controller.connect.auth.token=${CONTROLLER_AUTH_TOKEN} 27 | 28 | ## TLS configuration 29 | schemaRegistry.security.tls.enable=${TLS_ENABLED} 30 | schemaRegistry.security.tls.server.certificate.location=${TLS_CERT_FILE} 31 | schemaRegistry.security.tls.server.privateKey.location=${TLS_KEY_FILE} 32 | schemaRegistry.security.tls.server.privateKey.pwd.location=${TLS_KEY_PASSWORD_FILE} 33 | 34 | ## Authorization configuration 35 | schemaRegistry.security.auth.enable=${AUTHORIZATION_ENABLED} 36 | schemaRegistry.security.pwdAuthHandler.accountsDb.location=${USER_PASSWORD_FILE} 37 | schemaRegistry.security.auth.resource.identifier.domain=${AUTHORIZATION_DOMAIN_RESOURCE_IDENTIFIER} 38 | schemaRegistry.security.auth.resource.identifier.namespace=${AUTHORIZATION_NAMESPACE_RESOURCE_IDENTIFIER} 39 | schemaRegistry.security.auth.resource.identifier.group=${AUTHORIZATION_GROUP_RESOURCE_IDENTIFIER} 40 | schemaRegistry.security.auth.method.basic.disable=${DISABLE_BASIC_AUTH} -------------------------------------------------------------------------------- /server/src/test/java/io/pravega/schemaregistry/server/rest/auth/AuthHandlerManagerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.server.rest.auth; 11 | 12 | import io.pravega.auth.AuthConstants; 13 | import io.pravega.schemaregistry.server.rest.ServiceConfig; 14 | import io.pravega.shared.security.crypto.StrongPasswordProcessor; 15 | import org.junit.Test; 16 | 17 | import java.io.File; 18 | import java.io.FileWriter; 19 | import java.io.IOException; 20 | import java.security.NoSuchAlgorithmException; 21 | import java.security.spec.InvalidKeySpecException; 22 | 23 | import static org.junit.Assert.assertFalse; 24 | import static org.junit.Assert.assertTrue; 25 | 26 | 27 | public class AuthHandlerManagerTest { 28 | @Test 29 | public void testDisableBasicAuth() { 30 | ServiceConfig serviceConfig = ServiceConfig.builder() 31 | .authEnabled(true) 32 | .userPasswordFilePath(createAuthFile().getAbsolutePath()) 33 | .build(); 34 | AuthHandlerManager manager = new AuthHandlerManager(serviceConfig); 35 | 36 | assertTrue(manager.getHandlerMap().containsKey(AuthConstants.BASIC)); 37 | serviceConfig = ServiceConfig.builder().authEnabled(true).disablePasswordAuth(true) 38 | .build(); 39 | manager = new AuthHandlerManager(serviceConfig); 40 | assertFalse(manager.getHandlerMap().containsKey(AuthConstants.BASIC)); 41 | } 42 | 43 | private File createAuthFile() { 44 | try { 45 | File authFile = File.createTempFile("auth_file", ".txt"); 46 | StrongPasswordProcessor passwordEncryptor = StrongPasswordProcessor.builder().build(); 47 | 48 | try (FileWriter writer = new FileWriter(authFile.getAbsolutePath())) { 49 | String defaultPassword = passwordEncryptor.encryptPassword("password"); 50 | writer.write(String.format("%s:%s:%s%n", "admin", defaultPassword, "prn::*,READ_UPDATE;")); 51 | } 52 | return authFile; 53 | } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) { 54 | throw new RuntimeException(e); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/Backward.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * BackwardPolicy compatibility type which tells the service to check for backwardPolicy compatibility with latest schema. 25 | */ 26 | @ApiModel(description = "BackwardPolicy compatibility type which tells the service to check for backwardPolicy compatibility with latest schema.") 27 | 28 | public class Backward { 29 | @JsonProperty("name") 30 | private String name = null; 31 | 32 | public Backward name(String name) { 33 | this.name = name; 34 | return this; 35 | } 36 | 37 | /** 38 | * Get name 39 | * @return name 40 | **/ 41 | @JsonProperty("name") 42 | @ApiModelProperty(required = true, value = "") 43 | @NotNull 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | Backward backward = (Backward) o; 62 | return Objects.equals(this.name, backward.name); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(name); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class Backward {\n"); 75 | 76 | sb.append(" name: ").append(toIndentedString(name)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/VersionInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import io.pravega.common.ObjectBuilder; 13 | import lombok.AllArgsConstructor; 14 | import lombok.Builder; 15 | import lombok.Data; 16 | import lombok.NonNull; 17 | 18 | /** 19 | * Version information object that encapsulates properties that uniquely identify a specific version of a schema within a group. 20 | * This is generated by the service when a new schema is added to the group. It identifies the schema that is added and includes 21 | * the version and id assigned by the service to the schema. 22 | * 23 | * {@link VersionInfo#type} is same as {@link SchemaInfo#getType()} which represents the object type for which the version is computed. 24 | * {@link VersionInfo#version} the registry assigned monotonically increasing version number for the schema for specific object type. 25 | * Since the version number is per object type, so type and version number forms a unique pair. 26 | * {@link VersionInfo#id} This is an Id that is assigned by the service and uniquely identifies the schema version within 27 | * the group. The id are assigned as monotonically increasing numbers for all schemas added to the group. 28 | * So the id also represents the absolute order of the schema for all schemas in the group. 29 | */ 30 | @Data 31 | @Builder 32 | @AllArgsConstructor 33 | public class VersionInfo { 34 | /** 35 | * Object type which is declared in the corresponding {@link SchemaInfo#getType()} for the schemainfo that is identified 36 | * by this version info. 37 | */ 38 | private @NonNull final String type; 39 | 40 | /** 41 | * Serialization format for the schema. 42 | */ 43 | private @NonNull final String serializationFormatName; 44 | 45 | /** 46 | * A version number that identifies the position of schema among other schemas in the group that share the same 'type'. 47 | */ 48 | private final int version; 49 | /** 50 | * A position identifier that uniquely identifies the schema within a group and represents the order in which this 51 | * schema was included in the group. 52 | */ 53 | private final int id; 54 | 55 | public static class VersionInfoBuilder implements ObjectBuilder { 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /serializers/json/src/test/java/io/pravega/schemaregistry/serializer/json/schemas/SchemasTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.schemas; 11 | 12 | import com.fasterxml.jackson.databind.JsonNode; 13 | import io.pravega.schemaregistry.contract.data.SerializationFormat; 14 | import io.pravega.schemaregistry.serializer.shared.testobjs.DerivedUser1; 15 | import io.pravega.schemaregistry.serializer.shared.testobjs.DerivedUser2; 16 | import io.pravega.schemaregistry.serializer.shared.testobjs.User; 17 | import org.junit.Test; 18 | 19 | import static io.pravega.schemaregistry.serializer.json.testobjs.SchemaDefinitions.*; 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertNotNull; 22 | 23 | public class SchemasTest { 24 | @Test 25 | public void testJsonSchema() { 26 | JSONSchema schema = JSONSchema.of(User.class); 27 | assertNotNull(schema.getSchema()); 28 | assertEquals(schema.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 29 | 30 | JSONSchema schema2 = JSONSchema.of("Person", JSON_SCHEMA_STRING, String.class); 31 | assertNotNull(schema2.getSchema()); 32 | assertEquals(schema2.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 33 | 34 | JSONSchema schema3 = JSONSchema.of("", JSON_SCHEMA_STRING_DRAFT_4, JsonNode.class); 35 | assertNotNull(schema3.getSchema()); 36 | assertEquals(schema3.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 37 | 38 | JSONSchema schema4 = JSONSchema.of("", JSON_SCHEMA_STRING_DRAFT_7, JsonNode.class); 39 | assertNotNull(schema4.getSchema()); 40 | assertEquals(schema4.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 41 | 42 | JSONSchema baseSchema1 = JSONSchema.ofBaseType(DerivedUser1.class, User.class); 43 | assertNotNull(baseSchema1.getSchema()); 44 | assertEquals(baseSchema1.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 45 | 46 | JSONSchema baseSchema2 = JSONSchema.ofBaseType(DerivedUser2.class, User.class); 47 | assertNotNull(baseSchema2.getSchema()); 48 | assertEquals(baseSchema2.getSchemaInfo().getSerializationFormat(), SerializationFormat.Json); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/Valid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * Response object for validateSchema api. 25 | */ 26 | @ApiModel(description = "Response object for validateSchema api.") 27 | 28 | public class Valid { 29 | @JsonProperty("valid") 30 | private Boolean valid = null; 31 | 32 | public Valid valid(Boolean valid) { 33 | this.valid = valid; 34 | return this; 35 | } 36 | 37 | /** 38 | * Whether given schema is valid with respect to existing group schemas against the configured compatibility. 39 | * @return valid 40 | **/ 41 | @JsonProperty("valid") 42 | @ApiModelProperty(required = true, value = "Whether given schema is valid with respect to existing group schemas against the configured compatibility.") 43 | @NotNull 44 | public Boolean isValid() { 45 | return valid; 46 | } 47 | 48 | public void setValid(Boolean valid) { 49 | this.valid = valid; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | Valid valid = (Valid) o; 62 | return Objects.equals(this.valid, valid.valid); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(valid); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class Valid {\n"); 75 | 76 | sb.append(" valid: ").append(toIndentedString(valid)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /common/src/test/java/io/pravega/schemaregistry/common/FuturesUtilityTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.common; 11 | 12 | import com.google.common.collect.Lists; 13 | import org.junit.After; 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | 17 | import java.util.AbstractMap; 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.concurrent.CompletableFuture; 22 | import java.util.concurrent.Executors; 23 | import java.util.concurrent.ScheduledExecutorService; 24 | import java.util.function.BiFunction; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | public class FuturesUtilityTest { 30 | 31 | private ScheduledExecutorService executor; 32 | @Before 33 | public void setUp() { 34 | executor = Executors.newSingleThreadScheduledExecutor(); 35 | } 36 | 37 | @After 38 | public void tearDown() { 39 | executor.shutdownNow(); 40 | } 41 | 42 | @Test 43 | public void testFilteredWithTokenAndLimit() { 44 | List list = Lists.newArrayList(0, 1, 2, 0, 0, 3, 0, 4, 5, 6, 7, 0, 0, 0, 0, 8, 9, 10, 11, 0, 0, 0, 12, 0, 13); 45 | BiFunction>>> fn = (x, y) -> { 46 | if (x > list.size()) { 47 | return CompletableFuture.completedFuture(new AbstractMap.SimpleEntry<>(x, Collections.emptyList())); 48 | } 49 | return CompletableFuture.completedFuture(new AbstractMap.SimpleEntry<>(Math.min(x + y, list.size() + 1), list.subList(x, Math.min(x + y, list.size())))); 50 | }; 51 | 52 | Map.Entry> result = FuturesUtility.filteredWithTokenAndLimit(fn, x -> x != 0, 0, 10, executor).join(); 53 | assertEquals(result.getValue().size(), 10); 54 | assertTrue(result.getValue().stream().noneMatch(x -> x == 0)); 55 | assertEquals(result.getKey().intValue(), list.indexOf(11)); 56 | 57 | result = FuturesUtility.filteredWithTokenAndLimit(fn, x -> x != 0, result.getKey(), 10, executor).join(); 58 | assertEquals(result.getValue().size(), 3); 59 | assertTrue(result.getValue().stream().noneMatch(x -> x == 0)); 60 | assertEquals(result.getKey().intValue(), list.size() + 1); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /charts/schema-registry/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | # /** 2 | # * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | # * 4 | # * Licensed under the Apache License, Version 2.0 (the "License"); 5 | # * you may not use this file except in compliance with the License. 6 | # * You may obtain a copy of the License at 7 | # * 8 | # * http://www.apache.org/licenses/LICENSE-2.0 9 | # */ 10 | 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: {{ template "schema-registry.fullname" . }}-configmap 15 | namespace: {{ .Release.Namespace }} 16 | labels: 17 | {{ include "schema-registry.commonLabels" . | indent 4 }} 18 | data: 19 | "CONTROLLER_URL": "{{ .Values.controllerUri }}" 20 | "STORE_TYPE": "{{ .Values.storeType }}" 21 | {{- if .Values.pravega.tlsTrustStore }} 22 | "CONTROLLER_TLS_TRUST_STORE": "{{ .Values.pravega.tlsTrustStore }}" 23 | {{- end }} 24 | "CONTROLLER_TLS_VALIDATE_HOSTNAME": "{{ .Values.pravega.validateHostName }}" 25 | "AUTHORIZATION_ENABLED": "{{ .Values.authentication.enabled }}" 26 | "TLS_ENABLED": "{{ .Values.tls.enabled }}" 27 | "pravega_client_auth_loadDynamic": "{{ .Values.client.loadDynamic }}" 28 | "pravega_client_auth_method": "{{ .Values.client.method }}" 29 | "pravega_client_auth_token": "{{ .Values.client.token }}" 30 | {{- if .Values.authentication.enabled }} 31 | {{- if not .Values.authentication.disableBasicAuthentication }} 32 | "USER_PASSWORD_FILE": "/etc/auth-passwd-volume/{{ .Values.authentication.userPasswordFile }}" 33 | {{- end }} 34 | "DISABLE_BASIC_AUTH": "{{ .Values.authentication.disableBasicAuthentication }}" 35 | {{- if .Values.authentication.authDomainResourceIdentifier }} 36 | "AUTHORIZATION_DOMAIN_RESOURCE_IDENTIFIER": "{{ .Values.authentication.authDomainResourceIdentifier }}" 37 | {{- end }} 38 | {{- if .Values.authentication.authNamespaceResourceIdentifier }} 39 | "AUTHORIZATION_NAMESPACE_RESOURCE_IDENTIFIER": "{{ .Values.authentication.authNamespaceResourceIdentifier }}" 40 | {{- end }} 41 | {{- if .Values.authentication.authGroupResourceIdentifier }} 42 | "AUTHORIZATION_GROUP_RESOURCE_IDENTIFIER": "{{ .Values.authentication.authGroupResourceIdentifier }}" 43 | {{- end }} 44 | {{- end }} 45 | {{- if .Values.tls.enabled }} 46 | "TLS_CERT_FILE": "/etc/secret-volume/{{ .Values.tls.certFile }}" 47 | "TLS_KEY_FILE": "/etc/secret-volume/{{ .Values.tls.keyFile }}" 48 | "TLS_KEY_PASSWORD_FILE": "/etc/secret-volume/{{ .Values.tls.keyPasswordFile }}" 49 | {{- end }} 50 | {{- if and .Values.container .Values.container.command }} 51 | "PRE_START_CMD": "{{ .Values.container.command }}" 52 | {{- else }} 53 | "PRE_START_CMD": "" 54 | {{- end }} 55 | "log.level": "{{ .Values.logLevel }}" 56 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/data/SerializationFormat.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.contract.data; 11 | 12 | import com.google.common.base.Preconditions; 13 | import com.google.common.base.Strings; 14 | import lombok.AccessLevel; 15 | import lombok.Setter; 16 | 17 | /** 18 | * Different types of serialization formats used for serializing data. 19 | * Registry supports Avro, Protobuf and Json serialization formats but any custom type could be used with the registry using custom type. 20 | * 21 | * If a serialization format is not present in the enum it can be specified using {@link SerializationFormat#custom} with 22 | * {@link SerializationFormat#fullTypeName}. 23 | * Allowed values of {@link Compatibility} with {@link SerializationFormat#custom} are {@link Compatibility#allowAny} 24 | * or {@link Compatibility#denyAll}. 25 | */ 26 | 27 | public enum SerializationFormat { 28 | Avro, 29 | Protobuf, 30 | Json, 31 | Any, 32 | Custom; 33 | 34 | @Setter(AccessLevel.PRIVATE) 35 | private String fullTypeName; 36 | 37 | /** 38 | * Method to define a custom serialization format with a custom name. 39 | * @param fullTypeName Custom type name. 40 | * @return {@link SerializationFormat#Custom} with supplied custom type name. 41 | */ 42 | public static SerializationFormat custom(String fullTypeName) { 43 | Preconditions.checkArgument(!Strings.isNullOrEmpty(fullTypeName)); 44 | SerializationFormat type = SerializationFormat.Custom; 45 | type.setFullTypeName(fullTypeName); 46 | return type; 47 | } 48 | 49 | /** 50 | * Method to create a serialization format with a full name. 51 | * 52 | * @param fullTypeName Full type name. 53 | * @param format Serialization format. 54 | * @return {@link SerializationFormat#fullTypeName} with supplied custom type name. 55 | */ 56 | public static SerializationFormat withName(SerializationFormat format, String fullTypeName) { 57 | Preconditions.checkArgument(format != null); 58 | SerializationFormat type = SerializationFormat.valueOf(format.name()); 59 | type.setFullTypeName(fullTypeName); 60 | return type; 61 | } 62 | 63 | public String getFullTypeName() { 64 | return fullTypeName != null ? fullTypeName : this.name(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/ForwardTransitive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * ForwardPolicy compatibility type which tells the service to check for forwardPolicy compatibility with all previous schemas. 25 | */ 26 | @ApiModel(description = "ForwardPolicy compatibility type which tells the service to check for forwardPolicy compatibility with all previous schemas.") 27 | 28 | public class ForwardTransitive { 29 | @JsonProperty("name") 30 | private String name = null; 31 | 32 | public ForwardTransitive name(String name) { 33 | this.name = name; 34 | return this; 35 | } 36 | 37 | /** 38 | * Get name 39 | * @return name 40 | **/ 41 | @JsonProperty("name") 42 | @ApiModelProperty(required = true, value = "") 43 | @NotNull 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | ForwardTransitive forwardTransitive = (ForwardTransitive) o; 62 | return Objects.equals(this.name, forwardTransitive.name); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(name); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class ForwardTransitive {\n"); 75 | 76 | sb.append(" name: ").append(toIndentedString(name)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/BackwardTransitive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * BackwardPolicy compatibility type which tells the service to check for backwardPolicy compatibility with all previous schemas. 25 | */ 26 | @ApiModel(description = "BackwardPolicy compatibility type which tells the service to check for backwardPolicy compatibility with all previous schemas.") 27 | 28 | public class BackwardTransitive { 29 | @JsonProperty("name") 30 | private String name = null; 31 | 32 | public BackwardTransitive name(String name) { 33 | this.name = name; 34 | return this; 35 | } 36 | 37 | /** 38 | * Get name 39 | * @return name 40 | **/ 41 | @JsonProperty("name") 42 | @ApiModelProperty(required = true, value = "") 43 | @NotNull 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | BackwardTransitive backwardTransitive = (BackwardTransitive) o; 62 | return Objects.equals(this.name, backwardTransitive.name); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(name); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class BackwardTransitive {\n"); 75 | 76 | sb.append(" name: ").append(toIndentedString(name)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/EncodingId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * Encoding id that uniquely identifies a schema version and codec type pair. 25 | */ 26 | @ApiModel(description = "Encoding id that uniquely identifies a schema version and codec type pair.") 27 | 28 | public class EncodingId { 29 | @JsonProperty("encodingId") 30 | private Integer encodingId = null; 31 | 32 | public EncodingId encodingId(Integer encodingId) { 33 | this.encodingId = encodingId; 34 | return this; 35 | } 36 | 37 | /** 38 | * encoding id generated by service. 39 | * @return encodingId 40 | **/ 41 | @JsonProperty("encodingId") 42 | @ApiModelProperty(required = true, value = "encoding id generated by service.") 43 | @NotNull 44 | public Integer getEncodingId() { 45 | return encodingId; 46 | } 47 | 48 | public void setEncodingId(Integer encodingId) { 49 | this.encodingId = encodingId; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | EncodingId encodingId = (EncodingId) o; 62 | return Objects.equals(this.encodingId, encodingId.encodingId); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(encodingId); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class EncodingId {\n"); 75 | 76 | sb.append(" encodingId: ").append(toIndentedString(encodingId)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /serializers/shared/src/main/java/io/pravega/schemaregistry/serializer/shared/impl/EncodingCache.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.shared.impl; 11 | 12 | import com.google.common.annotations.VisibleForTesting; 13 | import com.google.common.cache.CacheBuilder; 14 | import com.google.common.cache.CacheLoader; 15 | import com.google.common.cache.LoadingCache; 16 | import io.pravega.common.Exceptions; 17 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 18 | import io.pravega.schemaregistry.client.exceptions.RegistryExceptions; 19 | import io.pravega.schemaregistry.contract.data.EncodingId; 20 | import io.pravega.schemaregistry.contract.data.EncodingInfo; 21 | 22 | import java.util.concurrent.ConcurrentMap; 23 | import java.util.concurrent.ExecutionException; 24 | 25 | /** 26 | * Local cache for storing schemas that are retrieved from the registry service. 27 | */ 28 | public class EncodingCache { 29 | private static final int MAXIMUM_SIZE = 1000; 30 | 31 | private final LoadingCache encodingCache; 32 | public EncodingCache(String groupId, SchemaRegistryClient schemaRegistryClient) { 33 | this(groupId, schemaRegistryClient, MAXIMUM_SIZE); 34 | } 35 | 36 | @VisibleForTesting 37 | EncodingCache(String groupId, SchemaRegistryClient schemaRegistryClient, int cacheSize) { 38 | encodingCache = CacheBuilder.newBuilder() 39 | .maximumSize(cacheSize) 40 | .build(new CacheLoader() { 41 | @Override 42 | public EncodingInfo load(EncodingId key) { 43 | return schemaRegistryClient.getEncodingInfo(groupId, key); 44 | } 45 | }); 46 | } 47 | 48 | EncodingInfo getGroupEncodingInfo(EncodingId encodingId) { 49 | try { 50 | return encodingCache.get(encodingId); 51 | } catch (ExecutionException e) { 52 | if (e.getCause() != null && Exceptions.unwrap(e.getCause()) instanceof RegistryExceptions) { 53 | throw (RegistryExceptions) e.getCause(); 54 | } else { 55 | throw new RuntimeException(e.getCause()); 56 | } 57 | } 58 | } 59 | 60 | @VisibleForTesting 61 | ConcurrentMap getMapForCache() { 62 | return encodingCache.asMap(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/groups/GroupsValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.groups; 11 | 12 | import io.pravega.common.ObjectBuilder; 13 | import io.pravega.common.io.serialization.RevisionDataInput; 14 | import io.pravega.common.io.serialization.RevisionDataOutput; 15 | import io.pravega.common.io.serialization.VersionedSerializer; 16 | import lombok.AllArgsConstructor; 17 | import lombok.Builder; 18 | import lombok.Data; 19 | import lombok.SneakyThrows; 20 | 21 | import java.io.IOException; 22 | 23 | /** 24 | * Groups listing record in groups table. 25 | */ 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | public class GroupsValue { 30 | public static final Serializer SERIALIZER = new Serializer(); 31 | 32 | private final String id; 33 | private final State state; 34 | 35 | @SneakyThrows(IOException.class) 36 | public byte[] toBytes() { 37 | return SERIALIZER.serialize(this).getCopy(); 38 | } 39 | 40 | @SneakyThrows(IOException.class) 41 | public static GroupsValue fromBytes(byte[] bytes) { 42 | return SERIALIZER.deserialize(bytes); 43 | } 44 | 45 | private static class GroupsValueBuilder implements ObjectBuilder { 46 | } 47 | 48 | static class Serializer extends VersionedSerializer.WithBuilder { 49 | @Override 50 | protected GroupsValue.GroupsValueBuilder newBuilder() { 51 | return GroupsValue.builder(); 52 | } 53 | 54 | @Override 55 | protected byte getWriteVersion() { 56 | return 0; 57 | } 58 | 59 | @Override 60 | protected void declareVersions() { 61 | version(0).revision(0, this::write00, this::read00); 62 | } 63 | 64 | private void write00(GroupsValue e, RevisionDataOutput target) throws IOException { 65 | target.writeUTF(e.id); 66 | target.writeCompactInt(e.state.ordinal()); 67 | } 68 | 69 | private void read00(RevisionDataInput source, GroupsValue.GroupsValueBuilder b) throws IOException { 70 | b.id(source.readUTF()); 71 | int ordinal = source.readCompactInt(); 72 | b.state(State.values()[ordinal]); 73 | } 74 | } 75 | 76 | public enum State { 77 | Creating, 78 | Active, 79 | Deleting 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.avro.impl; 11 | 12 | import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; 13 | import io.pravega.schemaregistry.client.SchemaRegistryClient; 14 | import io.pravega.schemaregistry.serializer.shared.codec.Encoder; 15 | import io.pravega.schemaregistry.contract.data.SchemaInfo; 16 | import io.pravega.schemaregistry.serializer.shared.impl.AbstractSerializer; 17 | import org.apache.avro.Schema; 18 | import org.apache.avro.generic.GenericDatumWriter; 19 | import org.apache.avro.generic.IndexedRecord; 20 | import org.apache.avro.io.BinaryEncoder; 21 | import org.apache.avro.io.EncoderFactory; 22 | import org.apache.avro.reflect.ReflectDatumWriter; 23 | import org.apache.avro.specific.SpecificDatumWriter; 24 | import org.apache.avro.specific.SpecificRecord; 25 | 26 | import java.io.IOException; 27 | import java.io.OutputStream; 28 | 29 | public class AvroSerializer extends AbstractSerializer { 30 | 31 | private final SpecificDatumWriter specificDatumWriter; 32 | private final GenericDatumWriter genericDatumWriter; 33 | private final ReflectDatumWriter reflectDatumWriter; 34 | 35 | public AvroSerializer(String groupId, SchemaRegistryClient client, AvroSchema schema, 36 | Encoder encoder, boolean registerSchema) { 37 | super(groupId, client, schema, encoder, registerSchema, true); 38 | Schema avroSchema = schema.getSchema(); 39 | this.specificDatumWriter = new SpecificDatumWriter<>(avroSchema); 40 | this.genericDatumWriter = new GenericDatumWriter<>(avroSchema); 41 | this.reflectDatumWriter = new ReflectDatumWriter<>(avroSchema); 42 | } 43 | 44 | @Override 45 | protected void serialize(T var, SchemaInfo schemaInfo, OutputStream outputStream) throws IOException { 46 | BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(outputStream, null); 47 | 48 | if (SpecificRecord.class.isAssignableFrom(var.getClass())) { 49 | specificDatumWriter.write(var, encoder); 50 | } else if (IndexedRecord.class.isAssignableFrom(var.getClass())) { 51 | genericDatumWriter.write(var, encoder); 52 | } else { 53 | reflectDatumWriter.write(var, encoder); 54 | } 55 | 56 | encoder.flush(); 57 | outputStream.flush(); 58 | } 59 | } -------------------------------------------------------------------------------- /server/src/main/java/io/pravega/schemaregistry/storage/impl/group/records/NamespaceAndGroup.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.storage.impl.group.records; 11 | 12 | import io.pravega.common.ObjectBuilder; 13 | import io.pravega.common.io.serialization.RevisionDataInput; 14 | import io.pravega.common.io.serialization.RevisionDataOutput; 15 | import io.pravega.common.io.serialization.VersionedSerializer; 16 | import lombok.Builder; 17 | import lombok.Data; 18 | import lombok.SneakyThrows; 19 | 20 | import java.io.IOException; 21 | 22 | @Data 23 | @Builder 24 | public class NamespaceAndGroup { 25 | public static final NamespaceAndGroup.Serializer SERIALIZER = new NamespaceAndGroup.Serializer(); 26 | 27 | private final String namespace; 28 | private final String groupId; 29 | 30 | public NamespaceAndGroup(String namespace, String groupId) { 31 | this.namespace = namespace == null ? "" : namespace; 32 | this.groupId = groupId; 33 | } 34 | 35 | @SneakyThrows(IOException.class) 36 | public byte[] toBytes() { 37 | return SERIALIZER.serialize(this).getCopy(); 38 | } 39 | 40 | @SneakyThrows(IOException.class) 41 | public static NamespaceAndGroup fromBytes(byte[] bytes) { 42 | return SERIALIZER.deserialize(bytes); 43 | } 44 | 45 | private static class NamespaceAndGroupBuilder implements ObjectBuilder { 46 | } 47 | 48 | public static class Serializer extends VersionedSerializer.WithBuilder { 49 | @Override 50 | protected NamespaceAndGroup.NamespaceAndGroupBuilder newBuilder() { 51 | return NamespaceAndGroup.builder(); 52 | } 53 | 54 | @Override 55 | protected byte getWriteVersion() { 56 | return 0; 57 | } 58 | 59 | @Override 60 | protected void declareVersions() { 61 | version(0).revision(0, this::write00, this::read00); 62 | } 63 | 64 | private void write00(NamespaceAndGroup e, RevisionDataOutput target) throws IOException { 65 | target.writeUTF(e.namespace); 66 | target.writeUTF(e.groupId); 67 | } 68 | 69 | private void read00(RevisionDataInput source, NamespaceAndGroup.NamespaceAndGroupBuilder b) throws IOException { 70 | b.namespace(source.readUTF()) 71 | .groupId(source.readUTF()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /serializers/json/src/test/java/io/pravega/schemaregistry/serializer/json/testobjs/SchemaDefinitions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.serializer.json.testobjs; 11 | 12 | public class SchemaDefinitions { 13 | public static final String JSON_SCHEMA_STRING = "{" + 14 | "\"title\": \"Person\", " + 15 | "\"type\": \"object\", " + 16 | "\"properties\": { " + 17 | "\"name\": {" + 18 | "\"type\": \"string\"" + 19 | "}," + 20 | "\"age\": {" + 21 | "\"type\": \"integer\", \"minimum\": 0" + 22 | "}" + 23 | "}" + 24 | "}"; 25 | 26 | public static final String JSON_SCHEMA_STRING_DRAFT_4 = "{\n" + 27 | " \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" + 28 | " \"title\": \"User\",\n" + 29 | " \"id\": \"UserV4\",\n" + 30 | " \"type\": \"object\",\n" + 31 | "\t\n" + 32 | " \"properties\": {\n" + 33 | "\t\n" + 34 | " \"id\": {\n" + 35 | " \"type\": \"integer\"\n" + 36 | " },\n" + 37 | "\t\t\n" + 38 | " \"name\": {\n" + 39 | " \"type\": \"string\"\n" + 40 | " },\n" + 41 | "\t\t\n" + 42 | " \"age\": {\n" + 43 | " \"type\": \"number\",\n" + 44 | " \"minimum\": 0,\n" + 45 | " \"exclusiveMinimum\": true\n" + 46 | " }\n" + 47 | " },\n" + 48 | "\t\n" + 49 | " \"required\": [\"id\", \"name\", \"age\"]\n" + 50 | "}"; 51 | 52 | public static final String JSON_SCHEMA_STRING_DRAFT_7 = "{\n" + 53 | " \"$id\": \"UserV7\",\n" + 54 | " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" + 55 | " \"title\": \"User\",\n" + 56 | " \"type\": \"object\",\n" + 57 | " \"properties\": {\n" + 58 | " \"firstName\": {\n" + 59 | " \"type\": \"string\"\n" + 60 | " },\n" + 61 | " \"lastName\": {\n" + 62 | " \"type\": \"string\"\n" + 63 | " },\n" + 64 | " \"age\": {\n" + 65 | " \"type\": \"integer\",\n" + 66 | " \"minimum\": 0\n" + 67 | " }\n" + 68 | " }\n" + 69 | "}"; 70 | } 71 | -------------------------------------------------------------------------------- /contract/src/main/java/io/pravega/schemaregistry/contract/generated/rest/model/ForwardPolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Pravega Schema Registry APIs 3 | * REST APIs for Pravega Schema Registry. 4 | * 5 | * OpenAPI spec version: 0.0.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package io.pravega.schemaregistry.contract.generated.rest.model; 15 | 16 | import java.util.Objects; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonCreator; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.*; 22 | 23 | /** 24 | * ForwardPolicy policy. 25 | */ 26 | @ApiModel(description = "ForwardPolicy policy.") 27 | 28 | public class ForwardPolicy { 29 | @JsonProperty("forwardPolicy") 30 | private Object forwardPolicy = null; 31 | 32 | public ForwardPolicy forwardPolicy(Object forwardPolicy) { 33 | this.forwardPolicy = forwardPolicy; 34 | return this; 35 | } 36 | 37 | /** 38 | * BackwardAndForward type forwardPolicy. Can be one of forward, forwardTill and forwardTransitive. 39 | * @return forwardPolicy 40 | **/ 41 | @JsonProperty("forwardPolicy") 42 | @ApiModelProperty(required = true, value = "BackwardAndForward type forwardPolicy. Can be one of forward, forwardTill and forwardTransitive.") 43 | @NotNull 44 | public Object getForwardPolicy() { 45 | return forwardPolicy; 46 | } 47 | 48 | public void setForwardPolicy(Object forwardPolicy) { 49 | this.forwardPolicy = forwardPolicy; 50 | } 51 | 52 | 53 | @Override 54 | public boolean equals(java.lang.Object o) { 55 | if (this == o) { 56 | return true; 57 | } 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | ForwardPolicy forwardPolicy = (ForwardPolicy) o; 62 | return Objects.equals(this.forwardPolicy, forwardPolicy.forwardPolicy); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(forwardPolicy); 68 | } 69 | 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | sb.append("class ForwardPolicy {\n"); 75 | 76 | sb.append(" forwardPolicy: ").append(toIndentedString(forwardPolicy)).append("\n"); 77 | sb.append("}"); 78 | return sb.toString(); 79 | } 80 | 81 | /** 82 | * Convert the given object to string with each line indented by 4 spaces 83 | * (except the first line). 84 | */ 85 | private String toIndentedString(java.lang.Object o) { 86 | if (o == null) { 87 | return "null"; 88 | } 89 | return o.toString().replace("\n", "\n "); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /client/src/test/java/io/pravega/schemaregistry/client/SchemaRegistryClientConfigTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | */ 10 | package io.pravega.schemaregistry.client; 11 | 12 | import io.pravega.schemaregistry.common.CredentialProvider; 13 | import org.junit.Test; 14 | 15 | import static org.junit.Assert.*; 16 | 17 | public class SchemaRegistryClientConfigTest { 18 | @Test 19 | public void testSSLConfig() { 20 | SchemaRegistryClientConfig config = SchemaRegistryClientConfig.builder().build(); 21 | assertNull(config.getCertificate()); 22 | assertNull(config.getTrustStore()); 23 | assertNull(config.getTrustStoreType()); 24 | assertNull(config.getTrustStorePassword()); 25 | 26 | config = SchemaRegistryClientConfig.builder().certificate("certPath").build(); 27 | assertEquals(config.getCertificate(), "certPath"); 28 | assertNull(config.getTrustStorePassword()); 29 | assertNull(config.getTrustStoreType()); 30 | assertNull(config.getTrustStorePassword()); 31 | 32 | config = SchemaRegistryClientConfig.builder().trustStore("trustStorePath", "JKS", null).build(); 33 | assertNull(config.getCertificate()); 34 | assertEquals(config.getTrustStore(), "trustStorePath"); 35 | assertEquals(config.getTrustStoreType(), "JKS"); 36 | assertNull(config.getTrustStorePassword()); 37 | 38 | config = SchemaRegistryClientConfig.builder().trustStore("trustStorePath", "JKS", "password").build(); 39 | assertNull(config.getCertificate()); 40 | assertEquals(config.getTrustStore(), "trustStorePath"); 41 | assertEquals(config.getTrustStoreType(), "JKS"); 42 | assertEquals(config.getTrustStorePassword(), "password"); 43 | } 44 | 45 | @Test 46 | public void testAuthConfig() { 47 | SchemaRegistryClientConfig config = SchemaRegistryClientConfig.builder().build(); 48 | assertFalse(config.isAuthEnabled()); 49 | 50 | config = SchemaRegistryClientConfig.builder().authentication(new CredentialProvider() { 51 | @Override 52 | public String getMethod() { 53 | return "method"; 54 | } 55 | 56 | @Override 57 | public String getToken() { 58 | return "token"; 59 | } 60 | }).build(); 61 | assertTrue(config.isAuthEnabled()); 62 | assertEquals("method", config.getCredentialProvider().getMethod()); 63 | assertEquals("token", config.getCredentialProvider().getToken()); 64 | } 65 | } 66 | --------------------------------------------------------------------------------