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

com.hazelcast.jet.sql.impl.connector.kafka.PropertiesResolver Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright 2024 Hazelcast Inc.
 *
 * Licensed under the Hazelcast Community License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://hazelcast.com/hazelcast-community-license
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.jet.sql.impl.connector.kafka;

import com.hazelcast.core.HazelcastJsonValue;
import com.hazelcast.jet.kafka.HazelcastKafkaAvroDeserializer;
import com.hazelcast.jet.kafka.HazelcastKafkaAvroSerializer;
import com.hazelcast.jet.kafka.impl.HazelcastJsonValueDeserializer;
import com.hazelcast.jet.kafka.impl.HazelcastJsonValueSerializer;
import com.hazelcast.jet.sql.impl.connector.keyvalue.JavaClassNameResolver;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import static com.hazelcast.jet.sql.impl.connector.SqlConnector.AVRO_FORMAT;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.JAVA_FORMAT;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.JSON_FLAT_FORMAT;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_KEY_AVRO_SCHEMA;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_KEY_CLASS;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_KEY_FORMAT;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_VALUE_AVRO_SCHEMA;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_VALUE_CLASS;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_VALUE_FORMAT;
import static com.hazelcast.jet.sql.impl.connector.SqlConnector.OPTION_PREFERRED_LOCAL_PARALLELISM;

final class PropertiesResolver {
    static final String KEY_SERIALIZER = "key.serializer";
    static final String KEY_DESERIALIZER = "key.deserializer";
    static final String VALUE_SERIALIZER = "value.serializer";
    static final String VALUE_DESERIALIZER = "value.deserializer";

    private static final Set NON_KAFKA_OPTIONS = Set.of(
            OPTION_KEY_FORMAT,
            OPTION_KEY_CLASS,
            OPTION_VALUE_FORMAT,
            OPTION_VALUE_CLASS,
            OPTION_PREFERRED_LOCAL_PARALLELISM
    );

    // using strings instead of canonical names to not fail without Kafka on the classpath

    private static final String SHORT_SERIALIZER = "org.apache.kafka.common.serialization.ShortSerializer";
    private static final String SHORT_DESERIALIZER = "org.apache.kafka.common.serialization.ShortDeserializer";

    private static final String INT_SERIALIZER = "org.apache.kafka.common.serialization.IntegerSerializer";
    private static final String INT_DESERIALIZER = "org.apache.kafka.common.serialization.IntegerDeserializer";

    private static final String LONG_SERIALIZER = "org.apache.kafka.common.serialization.LongSerializer";
    private static final String LONG_DESERIALIZER = "org.apache.kafka.common.serialization.LongDeserializer";

    private static final String FLOAT_SERIALIZER = "org.apache.kafka.common.serialization.FloatSerializer";
    private static final String FLOAT_DESERIALIZER = "org.apache.kafka.common.serialization.FloatDeserializer";

    private static final String DOUBLE_SERIALIZER = "org.apache.kafka.common.serialization.DoubleSerializer";
    private static final String DOUBLE_DESERIALIZER = "org.apache.kafka.common.serialization.DoubleDeserializer";

    private static final String STRING_SERIALIZER = "org.apache.kafka.common.serialization.StringSerializer";
    private static final String STRING_DESERIALIZER = "org.apache.kafka.common.serialization.StringDeserializer";

    private static final String CONFLUENT_AVRO_SERIALIZER = "io.confluent.kafka.serializers.KafkaAvroSerializer";
    private static final String CONFLUENT_AVRO_DESERIALIZER = "io.confluent.kafka.serializers.KafkaAvroDeserializer";

    private static final String HAZELCAST_AVRO_SERIALIZER = HazelcastKafkaAvroSerializer.class.getName();
    private static final String HAZELCAST_AVRO_DESERIALIZER = HazelcastKafkaAvroDeserializer.class.getName();

    private static final String BYTE_ARRAY_SERIALIZER = "org.apache.kafka.common.serialization.ByteArraySerializer";
    private static final String BYTE_ARRAY_DESERIALIZER = "org.apache.kafka.common.serialization.ByteArrayDeserializer";

    private static final String JSON_SERIALIZER = HazelcastJsonValueSerializer.class.getName();
    private static final String JSON_DESERIALIZER = HazelcastJsonValueDeserializer.class.getName();

    private PropertiesResolver() { }

    static Properties resolveConsumerProperties(Map options, Object keySchema, Object valueSchema) {
        Properties properties = from(options);

        withSerdeConsumerProperties(true, options, keySchema, properties);
        withSerdeConsumerProperties(false, options, valueSchema, properties);

        return properties;
    }

    static Properties resolveProducerProperties(Map options, Object keySchema, Object valueSchema) {
        Properties properties = from(options);

        withSerdeProducerProperties(true, options, keySchema, properties);
        withSerdeProducerProperties(false, options, valueSchema, properties);

        return properties;
    }

    private static Properties from(Map options) {
        Properties properties = new Properties();
        for (Entry entry : options.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();

            if (!NON_KAFKA_OPTIONS.contains(key)) {
                properties.put(key, value);
            }
        }
        return properties;
    }

    private static void withSerdeConsumerProperties(
            boolean isKey,
            Map options,
            Object schema,
            Properties properties
    ) {
        String deserializer = isKey ? KEY_DESERIALIZER : VALUE_DESERIALIZER;

        String format = options.get(isKey ? OPTION_KEY_FORMAT : OPTION_VALUE_FORMAT);
        if (format == null && isKey) {
            properties.putIfAbsent(deserializer, BYTE_ARRAY_DESERIALIZER);
        } else if (AVRO_FORMAT.equals(format)) {
            if (options.containsKey("schema.registry.url")) {
                properties.putIfAbsent(deserializer, CONFLUENT_AVRO_DESERIALIZER);
            } else {
                properties.putIfAbsent(deserializer, HAZELCAST_AVRO_DESERIALIZER);
                properties.put(isKey ? OPTION_KEY_AVRO_SCHEMA : OPTION_VALUE_AVRO_SCHEMA, schema);
            }
        } else if (JSON_FLAT_FORMAT.equals(format)) {
            properties.putIfAbsent(deserializer, BYTE_ARRAY_DESERIALIZER);
        } else if (JAVA_FORMAT.equals(format)) {
            String clazz = options.get(isKey ? OPTION_KEY_CLASS : OPTION_VALUE_CLASS);
            String deserializerClass = resolveDeserializer(clazz);
            if (deserializerClass != null) {
                properties.putIfAbsent(deserializer, deserializerClass);
            }
        } else {
            String resolvedClass = JavaClassNameResolver.resolveClassName(format);
            if (resolvedClass != null) {
                String deserializerClass = resolveDeserializer(resolvedClass);
                if (deserializerClass != null) {
                    properties.putIfAbsent(deserializer, deserializerClass);
                }
            }
        }
    }

    private static String resolveDeserializer(String clazz) {
        if (Short.class.getName().equals(clazz) || short.class.getName().equals(clazz)) {
            return SHORT_DESERIALIZER;
        } else if (Integer.class.getName().equals(clazz) || int.class.getName().equals(clazz)) {
            return INT_DESERIALIZER;
        } else if (Long.class.getName().equals(clazz) || long.class.getName().equals(clazz)) {
            return LONG_DESERIALIZER;
        } else if (Float.class.getName().equals(clazz) || float.class.getName().equals(clazz)) {
            return FLOAT_DESERIALIZER;
        } else if (Double.class.getName().equals(clazz) || double.class.getName().equals(clazz)) {
            return DOUBLE_DESERIALIZER;
        } else if (String.class.getName().equals(clazz)) {
            return STRING_DESERIALIZER;
        } else if (HazelcastJsonValue.class.getName().equals(clazz)) {
            return JSON_DESERIALIZER;
        } else {
            return null;
        }
    }

    private static void withSerdeProducerProperties(
            boolean isKey,
            Map options,
            Object schema,
            Properties properties
    ) {
        String serializer = isKey ? KEY_SERIALIZER : VALUE_SERIALIZER;

        String format = options.get(isKey ? OPTION_KEY_FORMAT : OPTION_VALUE_FORMAT);
        if (format == null && isKey) {
            properties.putIfAbsent(serializer, BYTE_ARRAY_SERIALIZER);
        } else if (AVRO_FORMAT.equals(format)) {
            if (options.containsKey("schema.registry.url")) {
                properties.putIfAbsent(serializer, CONFLUENT_AVRO_SERIALIZER);
            } else {
                properties.putIfAbsent(serializer, HAZELCAST_AVRO_SERIALIZER);
                properties.put(isKey ? OPTION_KEY_AVRO_SCHEMA : OPTION_VALUE_AVRO_SCHEMA, schema);
            }
        } else if (JSON_FLAT_FORMAT.equals(format)) {
            properties.putIfAbsent(serializer, BYTE_ARRAY_SERIALIZER);
        } else if (JAVA_FORMAT.equals(format)) {
            String clazz = options.get(isKey ? OPTION_KEY_CLASS : OPTION_VALUE_CLASS);
            String serializerClass = resolveSerializer(clazz);
            if (serializerClass != null) {
                properties.putIfAbsent(serializer, serializerClass);
            }
        } else {
            String resolvedClass = JavaClassNameResolver.resolveClassName(format);
            if (resolvedClass != null) {
                String serializerClass = resolveSerializer(resolvedClass);
                if (serializerClass != null) {
                    properties.putIfAbsent(serializer, serializerClass);
                }
            }
        }
    }

    private static String resolveSerializer(String clazz) {
        if (Short.class.getName().equals(clazz) || short.class.getName().equals(clazz)) {
            return SHORT_SERIALIZER;
        } else if (Integer.class.getName().equals(clazz) || int.class.getName().equals(clazz)) {
            return INT_SERIALIZER;
        } else if (Long.class.getName().equals(clazz) || long.class.getName().equals(clazz)) {
            return LONG_SERIALIZER;
        } else if (Float.class.getName().equals(clazz) || float.class.getName().equals(clazz)) {
            return FLOAT_SERIALIZER;
        } else if (Double.class.getName().equals(clazz) || double.class.getName().equals(clazz)) {
            return DOUBLE_SERIALIZER;
        } else if (String.class.getName().equals(clazz)) {
            return STRING_SERIALIZER;
        } else if (HazelcastJsonValue.class.getName().equals(clazz)) {
            return JSON_SERIALIZER;
        } else {
            return null;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy