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

com.scalar.db.sql.SqlTransactionFactory Maven / Gradle / Ivy

There is a newer version: 3.14.0
Show newest version
package com.scalar.db.sql;

import com.google.common.collect.ImmutableMap;
import com.scalar.db.sql.common.SqlError;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A factory class for {@link SqlTransactionManager} and {@link
 * SqlTwoPhaseCommitTransactionManager}.
 */
@ThreadSafe
public class SqlTransactionFactory {

  private static final Logger logger = LoggerFactory.getLogger(SqlTransactionFactory.class);

  // a cache for SqlTransactionProvider instances
  private static final Map SQL_TRANSACTION_PROVIDERS;

  static {
    // load SqlTransactionProvider with ServiceLoader
    ImmutableMap.Builder sqlTransactionProviderBuilder =
        ImmutableMap.builder();
    for (SqlTransactionProvider sqlTransactionProvider :
        ServiceLoader.load(SqlTransactionProvider.class)) {
      sqlTransactionProviderBuilder.put(
          sqlTransactionProvider.getName().toLowerCase(Locale.ROOT), sqlTransactionProvider);
    }
    SQL_TRANSACTION_PROVIDERS = sqlTransactionProviderBuilder.build();
  }

  private final SqlConfig config;
  private final Properties properties;

  private SqlTransactionFactory(Properties properties) {
    config = new SqlConfig(properties);
    this.properties = new Properties();
    this.properties.putAll(properties);
  }

  /**
   * Creates an instance of {@link SqlTransactionManager} for the connection mode.
   *
   * @return an instance of {@link SqlTransactionManager} for the connection mode
   */
  public SqlTransactionManager createSqlTransactionManager() {
    return getSqlTransactionProvider(config.getConnectionMode().orElse(null))
        .createSqlTransactionManager(properties);
  }

  /**
   * Creates an instance of {@link SqlTwoPhaseCommitTransactionManager} for the connection mode.
   *
   * @return an instance of {@link SqlTwoPhaseCommitTransactionManager} for the connection mode. If
   *     the transaction manager does not support the two-phase commit interface, returns {@code
   *     null}.
   */
  @Nullable
  public SqlTwoPhaseCommitTransactionManager createSqlTwoPhaseCommitTransactionManager() {
    return getSqlTransactionProvider(config.getConnectionMode().orElse(null))
        .createSqlTwoPhaseCommitTransactionManager(properties);
  }

  private SqlTransactionProvider getSqlTransactionProvider(@Nullable String connectionMode) {
    if (SQL_TRANSACTION_PROVIDERS.isEmpty()) {
      throw new IllegalArgumentException(
          SqlError.NO_CONNECTION_MODE_IMPLEMENTATIONS.buildMessage());
    }

    if (connectionMode == null) {
      // if the connection mode is not specified, use the only provider if there is only one
      if (SQL_TRANSACTION_PROVIDERS.size() == 1) {
        SqlTransactionProvider provider = SQL_TRANSACTION_PROVIDERS.values().iterator().next();
        logger.info(
            "Connection mode is not specified. Only one connection mode is found. Using it: {}",
            provider.getName());
        return provider;
      }

      throw new IllegalArgumentException(
          SqlError.CONNECTION_MODE_NOT_SPECIFIED_BUT_MULTIPLE_IMPLEMENTATIONS_FOUND.buildMessage(
              SQL_TRANSACTION_PROVIDERS.keySet()));
    }

    String lowerCaseConnectionMode = connectionMode.toLowerCase(Locale.ROOT);
    if (!SQL_TRANSACTION_PROVIDERS.containsKey(lowerCaseConnectionMode)) {
      throw new IllegalArgumentException(
          SqlError.CONNECTION_MODE_NOT_FOUND.buildMessage(
              connectionMode, SQL_TRANSACTION_PROVIDERS.keySet()));
    }
    return SQL_TRANSACTION_PROVIDERS.get(lowerCaseConnectionMode);
  }

  /**
   * Returns a builder object for {@link SqlTransactionFactory}.
   *
   * @return a builder object for {@link SqlTransactionFactory}
   */
  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {
    private final Properties properties = new Properties();

    /**
     * Specifies a properties file path.
     *
     * @param path a properties file path
     * @return this object
     */
    public Builder withPropertiesFile(String path) {
      return withPropertiesFile(Paths.get(path));
    }

    /**
     * Specifies a properties file path.
     *
     * @param path a properties file path
     * @return this object
     */
    public Builder withPropertiesFile(Path path) {
      try (InputStream inputStream = Files.newInputStream(path)) {
        properties.load(inputStream);
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
      return this;
    }

    /**
     * Adds a property.
     *
     * @param name a property name
     * @param value a property value
     * @return this object
     */
    public Builder withProperty(String name, String value) {
      properties.setProperty(name, value);
      return this;
    }

    /**
     * Adds properties.
     *
     * @param properties properties to add
     * @return this object
     */
    public Builder withProperties(Properties properties) {
      this.properties.putAll(properties);
      return this;
    }

    /**
     * Specifies a connection mode.
     *
     * @param connectionMode a connection mode
     * @return this object
     */
    public Builder withConnectionMode(String connectionMode) {
      properties.setProperty(SqlConfig.CONNECTION_MODE, connectionMode);
      return this;
    }

    /**
     * Builds a {@link SqlTransactionFactory} object with the specified configurations.
     *
     * @return a {@link SqlTransactionFactory} object
     */
    public SqlTransactionFactory build() {
      return new SqlTransactionFactory(properties);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy