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

me.dinowernli.grpc.polyglot.config.ConfigurationLoader Maven / Gradle / Ivy

package me.dinowernli.grpc.polyglot.config;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.protobuf.util.JsonFormat;

import polyglot.ConfigProto.Configuration;
import polyglot.ConfigProto.ConfigurationSet;
import polyglot.ConfigProto.OutputConfiguration.Destination;

/** A utility which manipulating and reading a single {@link ConfigurationSet}. */
public class ConfigurationLoader {
  private static final String DEFAULT_FILE_NAME = "config.pb.json";
  private static final String DEFAULT_LOCATION = ".polyglot";

  /** If this is absent, we hand out default instances of configs. */
  private final Optional configSet;

  /** Optional overrides for the configuration. */
  private final Optional maybeOverrides;

  /**
   * Returns a {@link ConfigurationLoader} backed by a {@link ConfigurationSet} in the current
   * user's home directory. If no such file exists, it falls back to a default config.
   */
  public static ConfigurationLoader forDefaultConfigSet() {
    String homeDirectory = System.getProperty("user.home");
    Path defaultLocation = Paths.get(homeDirectory, DEFAULT_LOCATION, DEFAULT_FILE_NAME);
    if (Files.exists(defaultLocation)) {
      return ConfigurationLoader.forFile(defaultLocation);
    } else {
      return new ConfigurationLoader(Optional.empty(), Optional.empty());
    }
  }

  /** Constructs a {@link ConfigurationLoader} from an explicit {@link ConfigurationSet}. */
  public static ConfigurationLoader forConfigSet(ConfigurationSet configSet) {
    return new ConfigurationLoader(Optional.of(configSet), Optional.empty() /* overrides */);
  }

  /** Returns a loader backed by config set obtained from the supplied file. */
  public static ConfigurationLoader forFile(Path configFile) {
    try {
      ConfigurationSet.Builder configSetBuilder = ConfigurationSet.newBuilder();
      String fileContent = Joiner.on('\n').join(Files.readAllLines(configFile));
      JsonFormat.parser().merge(fileContent, configSetBuilder);
      return ConfigurationLoader.forConfigSet(configSetBuilder.build());
    } catch (IOException e) {
      throw new RuntimeException("Unable to read config file: " + configFile.toString(), e);
    }
  }

  @VisibleForTesting
  ConfigurationLoader(Optional configSet, Optional maybeOverrides) {
    this.configSet = configSet;
    this.maybeOverrides = maybeOverrides;
  }

  /** Returns a new instance of {@link ConfigurationLoader} with the supplied overrides. */
  public ConfigurationLoader withOverrides(CommandLineArgs overrides) {
    return new ConfigurationLoader(configSet, Optional.of(overrides));
  }

  /** Returns the default configuration from the loaded configuration set. */
  public Configuration getDefaultConfiguration() {
    return applyOverrides(getDefaultConfigurationInternal());
  }

  /** Returns a config with the supplied name and throws if no such config is found. */
  public Configuration getNamedConfiguration(String name) {
    return applyOverrides(getNamedConfigurationInternal(name));
  }

  private Configuration getDefaultConfigurationInternal() {
    if (isEmptyConfig()) {
      return Configuration.getDefaultInstance();
    }
    if (configSet.get().getConfigurationsList().isEmpty()) {
      throw new IllegalStateException("No configs present in config set");
    }
    return configSet.get().getConfigurations(0);
  }

  private Configuration getNamedConfigurationInternal(String name) {
    Preconditions.checkState(!isEmptyConfig(), "Cannot load named config with a config set");
    return configSet.get().getConfigurationsList().stream()
        .filter(config -> config.getName().equals(name))
        .findAny()
        .orElseThrow(() -> new IllegalArgumentException("Could not find named config: " + name));
  }

  /** Returns the {@link Configuration} with overrides, if any, applied to it. */
  private Configuration applyOverrides(Configuration configuration) {
    if (!maybeOverrides.isPresent()) {
      return configuration;
    }

    CommandLineArgs overrides = maybeOverrides.get();
    Configuration.Builder resultBuilder = configuration.toBuilder();

    resultBuilder.getProtoConfigBuilder().setUseReflection(overrides.useReflection());

    overrides.useTls().ifPresent(resultBuilder.getCallConfigBuilder()::setUseTls);
    overrides.outputFilePath().ifPresent(path -> {
      resultBuilder.getOutputConfigBuilder().setDestination(Destination.FILE);
      resultBuilder.getOutputConfigBuilder().setFilePath(path.toString());
    });

    resultBuilder.getProtoConfigBuilder().addAllIncludePaths(
        overrides.additionalProtocIncludes().stream()
            .map(Path::toString)
            .collect(Collectors.toList()));

    overrides.protoDiscoveryRoot().ifPresent(
        root -> resultBuilder.getProtoConfigBuilder().setProtoDiscoveryRoot(root.toString()));

    overrides.getRpcDeadlineMs().ifPresent(
        resultBuilder.getCallConfigBuilder()::setDeadlineMs);

    overrides.tlsCaCertPath().ifPresent(
        path -> resultBuilder.getCallConfigBuilder().setTlsCaCertPath(path.toString()));

    overrides.tlsClientCertPath().ifPresent(
        path -> resultBuilder.getCallConfigBuilder().setTlsClientCertPath(path.toString()));

    overrides.tlsClientKeyPath().ifPresent(
        path -> resultBuilder.getCallConfigBuilder().setTlsClientKeyPath(path.toString()));

    overrides.tlsClientOverrideAuthority()
        .ifPresent(resultBuilder.getCallConfigBuilder()::setTlsClientOverrideAuthority);

    overrides.metadata().ifPresent(metadata -> {
      for (Map.Entry keyValue : metadata.entries().asList()) {
        resultBuilder.getCallConfigBuilder().addMetadataBuilder()
            .setName(keyValue.getKey())
            .setValue(keyValue.getValue())
            .build();
      }
    });

    return resultBuilder.build();
  }

  /** Returns false iff this is backed by a real config set (rather than the special empty one). */
  private boolean isEmptyConfig() {
    return !configSet.isPresent();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy