All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.streamnative.pulsar.handlers.kop.schemaregistry.resources.SchemaResource Maven / Gradle / Ivy

There is a newer version: 4.0.0.4
Show newest version
/**
 * Copyright (c) 2019 - 2024 StreamNative, Inc.. All Rights Reserved.
 */
/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.streamnative.pulsar.handlers.kop.schemaregistry.resources;

import com.fasterxml.jackson.annotation.JsonInclude;
import io.netty.handler.codec.http.FullHttpRequest;
import io.streamnative.pulsar.handlers.kop.schemaregistry.HttpJsonRequestProcessor;
import io.streamnative.pulsar.handlers.kop.schemaregistry.SchemaRegistryHandler;
import io.streamnative.pulsar.handlers.kop.schemaregistry.exceptions.Errors;
import io.streamnative.pulsar.handlers.kop.schemaregistry.model.Schema;
import io.streamnative.pulsar.handlers.kop.schemaregistry.model.SchemaStorage;
import io.streamnative.pulsar.handlers.kop.schemaregistry.model.SchemaStorageAccessor;
import io.streamnative.pulsar.handlers.kop.schemaregistry.model.rest.SchemaReference;
import io.streamnative.pulsar.handlers.kop.schemaregistry.utils.SubjectUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;

public class SchemaResource extends AbstractResource {

    // type boolean, default false
    public static final String QUERY_PARAM_DELETED = "deleted";

    public SchemaResource(SchemaStorageAccessor schemaStorageAccessor,
                          String defaultNamespace) {
        super(schemaStorageAccessor, defaultNamespace);
    }

    /**
     * Register all processors.
     * @param schemaRegistryHandler
     */
    public void register(SchemaRegistryHandler schemaRegistryHandler) {
        schemaRegistryHandler.addProcessor(new GetSchemaById());
        schemaRegistryHandler.addProcessor(new GetSchemaStringById());
        schemaRegistryHandler.addProcessor(new GetSchemaTypes());
        schemaRegistryHandler.addProcessor(new GetVersions());
        schemaRegistryHandler.addProcessor(new GetSubjects());
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public static final class GetSchemaResponse {
        private String schema;
        private String schemaType;
        private List references;
        //todo: metadata, ruleSet, maxId

        public String getSchemaType() {
            return "AVRO".equals(schemaType) ? null : schemaType;
        }
    }

    // /schemas/types
    public static class GetSchemaTypes extends HttpJsonRequestProcessor> {

        public GetSchemaTypes() {
            super(Void.class, "/schemas/types", GET);
        }

        @Override
        protected CompletableFuture> processRequest(Void payload, List patternGroups,
                                                                 FullHttpRequest request,
                                                                 Map> queryParams,
                                                                 String currentTenant) {
            return CompletableFuture.completedFuture(Schema.getAllTypes());
        }

    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static final class SubjectVersionPair {
        private String subject;
        private int version;
    }

    // GET /schemas/ids/{int: id}
    public class GetSchemaById extends HttpJsonRequestProcessor {

        private static final String QUERY_PARAM_SUBJECT = "subject";

        public GetSchemaById() {
            super(Void.class, "/schemas/ids/" + INT_PATTERN, GET);
        }

        @Override
        protected CompletableFuture processRequest(Void payload,
                                                                      List patternGroups,
                                                                      FullHttpRequest request,
                                                                      Map> queryParams,
                                                                      String currentTenant)
                throws Exception {
            String querySubject = getStringQueryParam(QUERY_PARAM_SUBJECT, null, queryParams);
            final String subject = querySubject == null ? null : SubjectUtils.normalize(querySubject, defaultNamespace);
            int id = getInt(0, patternGroups);
            SchemaStorage schemaStorage = getSchemaStorage(currentTenant);
            CompletableFuture> schemasFuture = schemaStorage.findSchemaById(id, false);
            return schemasFuture.thenApply(list -> {
                if (CollectionUtils.isEmpty(list)) {
                    throw Errors.schemaNotFoundException(id);
                }
                if (subject == null) {
                    return new GetSchemaResponse(list.get(0).getSchema(), list.get(0).getType(),
                        list.get(0).getReferences());
                }
                for (Schema schema : list) {
                    if (schema.getSubject().equals(subject)) {
                        return new GetSchemaResponse(schema.getSchema(), schema.getType(),
                            schema.getReferences());
                    }
                }
                throw Errors.schemaNotFoundException(id);
            });
        }
    }

    // GET /schemas/ids/{int: id}/schema     Get one schema string
    public class GetSchemaStringById extends HttpJsonRequestProcessor {

        public GetSchemaStringById() {
            super(Void.class, "/schemas/ids/" + INT_PATTERN + "/schema", GET);
        }

        @Override
        protected CompletableFuture processRequest(Void payload, List patternGroups,
                                                           FullHttpRequest request,
                                                           Map> queryParams,
                                                           String currentTenant)
                throws Exception {
            int id = getInt(0, patternGroups);
            SchemaStorage schemaStorage = getSchemaStorage(currentTenant);
            CompletableFuture> schemasFuture = schemaStorage.findSchemaById(id, false);
            return schemasFuture.thenApply(list -> {
                if (CollectionUtils.isEmpty(list)) {
                    return null;
                }
                return list.get(0).getSchema();
            });
        }

    }

    // GET /schemas/ids/{int: id}/versions
    public class GetVersions extends HttpJsonRequestProcessor> {

        public GetVersions() {
            super(Void.class, "/schemas/ids/" + INT_PATTERN + "/versions", GET);
        }

        @Override
        protected CompletableFuture> processRequest(Void payload,
                                                                             List patternGroups,
                                                                             FullHttpRequest request,
                                                                             Map> queryParams,
                                                                             String currentTenant)
                throws Exception {
            SchemaStorage schemaStorage = getSchemaStorage(currentTenant);
            boolean lookupDeleted = getBooleanQueryParam(QUERY_PARAM_DELETED, "false", queryParams);
            int id = getInt(0, patternGroups);
            CompletableFuture> schemasFuture = schemaStorage.findSchemaById(id, lookupDeleted);
            return schemasFuture.thenApply(list -> {
                if (CollectionUtils.isEmpty(list)) {
                    return null;
                }
                return list.stream()
                        .map(s -> new SubjectVersionPair(s.getSubject(), s.getVersion()))
                        .collect(Collectors.toList());
            });
        }

    }

    // GET /schemas/ids/{int: id}/subjects
    public class GetSubjects extends HttpJsonRequestProcessor> {

        public GetSubjects() {
            super(Void.class, "/schemas/ids/" + INT_PATTERN + "/subjects", GET);
        }

        @Override
        protected CompletableFuture> processRequest(
                Void payload, List patternGroups, FullHttpRequest request,
                Map> queryParams,
                String currentTenant) throws Exception {
            boolean lookupDeleted = getBooleanQueryParam(QUERY_PARAM_DELETED, "false", queryParams);
            int id = getInt(0, patternGroups);
            SchemaStorage schemaStorage = getSchemaStorage(currentTenant);
            return schemaStorage.findSchemaById(id, lookupDeleted).thenApply(schemas -> {
                if (CollectionUtils.isEmpty(schemas)) {
                    throw Errors.schemaNotFoundException();
                }
                return schemas.stream().map(Schema::getSubject).collect(Collectors.toSet());
            });
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy