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

ru.playa.keycloak.kafka.Configuration Maven / Gradle / Ivy

package ru.playa.keycloak.kafka;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.ByteArraySerializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.jboss.logging.Logger;

/**
 * Utility class for handling Kafka configuration settings.
 *
 * @author Anatoliy Pokhresnyi
 */
public final class Configuration {

    /**
     * Logger.
     */
    private static final Logger LOGGER = Logger.getLogger(Configuration.class);

    /**
     * Default prefix.
     */
    private static final String KEYCLOAK_PREFIX = "keycloak.";

    /**
     * Kafka client settings prefix.
     */
    private static final String KAFKA_PREFIX = "kafka.";

    /**
     * Topic for login events.
     */
    private static final String EVENT_TOPIC = KEYCLOAK_PREFIX + KAFKA_PREFIX + "topic.login";

    /**
     * Topic for admin events.
     */
    private static final String ADMIN_EVENT_TOPIC = KEYCLOAK_PREFIX + KAFKA_PREFIX + "topic.admin";

    /**
     * Asynchronous.
     */
    private static final String KEYCLOAK_SYNC = KEYCLOAK_PREFIX + "sync";

    /**
     * Bootstrap server.
     */
    private static final String KAFKA_BOOTSTRAP_SERVERS_CONFIG = KAFKA_PREFIX + ProducerConfig.BOOTSTRAP_SERVERS_CONFIG;

    /**
     * Acknowledge.
     */
    private static final String KAFKA_ACKS = KAFKA_PREFIX + ProducerConfig.ACKS_CONFIG;

    /**
     * Kafka client configuration variable name.
     */
    private static final String KEYCLOAK_KAFKA_CONFIG_NAME = "KEYCLOAK_KAFKA_CONFIG";

    /**
     * Default configuration.
     */
    private static final String KEYCLOAK_KAFKA_CONFIG_VALUE = "/keycloak-kafka.properties";

    /**
     * Jboss configuration directory.
     */
    private static final String JBOSS_CONFIG_DIR = "jboss.server.config.dir";

    /**
     * Constructor.
     */
    private Configuration() {

    }

    /**
     * Getting a topic for admin events.
     *
     * @return Topic.
     */
    public static synchronized String getAdminEventTopic() {
        return getConfigurationValue(loadDefaultConfiguration(), ADMIN_EVENT_TOPIC, "keycloak-admin");
    }

    /**
     * Getting a topic for login events.
     *
     * @return Topic.
     */
    public static synchronized String getLoginEventTopic() {
        return getConfigurationValue(loadDefaultConfiguration(), EVENT_TOPIC, "keycloak-login");
    }

    /**
     * Acknowledge.
     *
     * @return Acknowledge.
     */
    public static synchronized boolean isSync() {
        String value = getConfigurationValue(loadDefaultConfiguration(), KEYCLOAK_SYNC, "true");

        return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("on") || value.equalsIgnoreCase("1");
    }

    /**
     * Getting producer for admin events.
     *
     * @return Producer.
     */
    public static synchronized KafkaProducer getKafkaAdminEventProducer() {
        Properties properties = loadDefaultConfiguration();

        return new KafkaProducer<>(
                loadKafkaConfiguration(properties), new StringSerializer(), new ByteArraySerializer()
        );
    }

    /**
     * Getting producer for login events.
     *
     * @return Producer.
     */
    public static synchronized KafkaProducer getKafkaLoginEventProducer() {
        Properties properties = loadDefaultConfiguration();

        return new KafkaProducer<>(
                loadKafkaConfiguration(properties), new StringSerializer(), new ByteArraySerializer()
        );
    }

    /**
     * Getting the value of a variable from a configuration file or a default value.
     *
     * @param properties Properties.
     * @param key Key.
     * @param defaultValue Default value.
     * @return Value.
     */
    private static String getConfigurationValue(Properties properties, String key, String defaultValue) {
        return properties.getProperty(key, defaultValue);
    }

    /**
     * Set variable if absent.
     *
     * @param properties Properties.
     * @param key Key.
     * @param defaultValue Default value.
     */
    private static void ifAbsentThenSet(Properties properties, String key, String defaultValue) {
        if (isEmpty(properties.getProperty(key))) {
            properties.setProperty(key, defaultValue);
        }

        String newValue = getenv(key, null);
        String quarkusValue = getenv(key.replaceAll("\\.", "_").toUpperCase(), null);

        if (isEmpty(newValue) && isEmpty(quarkusValue)) {
            LOGGER.infof("Variable %s not overridden", key);

            return;
        }

        if (isEmpty(newValue)) {
            LOGGER.infof("Variable %s is overridden. New value %s", key, quarkusValue);

            properties.setProperty(key, quarkusValue);
        } else {
            LOGGER.infof("Variable %s is overridden. New value %s", key, newValue);

            properties.setProperty(key, newValue);
        }
    }

    /**
     * Check for emptiness.
     *
     * @param value Value.
     * @return String is empty.
     */
    private static boolean isEmpty(String value) {
        return value == null || value.isEmpty();
    }

    /**
     * Getting a variable from environment variables.
     *
     * @param key Key.
     * @param defaultValue Default value.
     * @return Value.
     */
    private static String getenv(String key, String defaultValue) {
        String env = System.getenv(key);
        String property = System.getProperty(key);

        if (env == null && property == null) {
            return defaultValue;
        }

        return env == null ? property : env;
    }

    /**
     * Loading default configuration.
     *
     * @return Default configuration.
     */
    private static Properties loadDefaultConfiguration() {
        String filename = getenv(
                KEYCLOAK_KAFKA_CONFIG_NAME,
                getenv(JBOSS_CONFIG_DIR, "") + KEYCLOAK_KAFKA_CONFIG_VALUE
        );
        Properties properties = new Properties();

        try {
            properties.load(new FileInputStream(filename));
        } catch (IOException ignored) {
        }

        ifAbsentThenSet(properties, ADMIN_EVENT_TOPIC, "keycloak-admin");
        ifAbsentThenSet(properties, EVENT_TOPIC, "keycloak-login");
        ifAbsentThenSet(properties, KEYCLOAK_SYNC, "true");
        ifAbsentThenSet(properties, KAFKA_BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        ifAbsentThenSet(properties, KAFKA_ACKS, "1");

        LOGGER.infof("Loading configuration for file or enviroment variable %s", properties);

        return properties;
    }

    /**
     * Loading Kafka configuration.
     *
     * @param properties Properties.
     * @return Kafka configuration.
     */
    private static Properties loadKafkaConfiguration(Properties properties) {
        Properties kafka = new Properties();

        properties
                .stringPropertyNames()
                .stream()
                .filter(name -> !name.startsWith(KEYCLOAK_PREFIX))
                .filter(name -> !(KAFKA_PREFIX + ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG).equals(name))
                .filter(name -> !ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG.equals(name))
                .filter(name -> !(KAFKA_PREFIX + ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG).equals(name))
                .filter(name -> !ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG.equals(name))
                .forEach(name -> {
                    String newName = name.startsWith(KAFKA_PREFIX) ? name.replaceFirst(KAFKA_PREFIX, "") : name;

                    kafka.setProperty(newName, properties.getProperty(name));
                });

        LOGGER.infof("Loading Kafka configuration %s", kafka);

        return kafka;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy