content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements. See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 org.apache.kafka.common.security.oauthbearer.internals.expiring;
  
  import org.apache.kafka.common.config.SaslConfigs;
  
  import java.util.Map;
  import java.util.Objects;
  
  /**
   * Immutable refresh-related configuration for expiring credentials that can be
   * parsed from a producer/consumer/broker config.
   */
  public class ExpiringCredentialRefreshConfig {
      private final double loginRefreshWindowFactor;
      private final double loginRefreshWindowJitter;
      private final short loginRefreshMinPeriodSeconds;
      private final short loginRefreshBufferSeconds;
      private final boolean loginRefreshReloginAllowedBeforeLogout;
  
      /**
       * Constructor based on producer/consumer/broker configs and the indicated value
       * for whether or not client relogin is allowed before logout
       * 
       * @param configs
       *            the mandatory (but possibly empty) producer/consumer/broker
       *            configs upon which to build this instance
       * @param clientReloginAllowedBeforeLogout
       *            if the {@code LoginModule} and {@code SaslClient} implementations
       *            support multiple simultaneous login contexts on a single
       *            {@code Subject} at the same time. If true, then upon refresh,
       *            logout will only be invoked on the original {@code LoginContext}
       *            after a new one successfully logs in. This can be helpful if the
       *            original credential still has some lifetime left when an attempt
       *            to refresh the credential fails; the client will still be able to
       *            create new connections as long as the original credential remains
       *            valid. Otherwise, if logout is immediately invoked prior to
       *            relogin, a relogin failure leaves the client without the ability
       *            to connect until relogin does in fact succeed.
       */
      public ExpiringCredentialRefreshConfig(Map<String, ?> configs, boolean clientReloginAllowedBeforeLogout) {
          Objects.requireNonNull(configs);
          this.loginRefreshWindowFactor = (Double) configs.get(SaslConfigs.SASL_LOGIN_REFRESH_WINDOW_FACTOR);
          this.loginRefreshWindowJitter = (Double) configs.get(SaslConfigs.SASL_LOGIN_REFRESH_WINDOW_JITTER);
          this.loginRefreshMinPeriodSeconds = (Short) configs.get(SaslConfigs.SASL_LOGIN_REFRESH_MIN_PERIOD_SECONDS);
          this.loginRefreshBufferSeconds = (Short) configs.get(SaslConfigs.SASL_LOGIN_REFRESH_BUFFER_SECONDS);
          this.loginRefreshReloginAllowedBeforeLogout = clientReloginAllowedBeforeLogout;
      }
  
      /**
       * Background login refresh thread will sleep until the specified window factor
       * relative to the credential's total lifetime has been reached, at which time
       * it will try to refresh the credential.
       * 
       * @return the login refresh window factor
       */
      public double loginRefreshWindowFactor() {
          return loginRefreshWindowFactor;
      }
  
      /**
       * Amount of random jitter added to the background login refresh thread's sleep
       * time.
       * 
       * @return the login refresh window jitter
       */
      public double loginRefreshWindowJitter() {
          return loginRefreshWindowJitter;
      }
  
      /**
       * The desired minimum time between checks by the background login refresh
       * thread, in seconds
       * 
       * @return the desired minimum refresh period, in seconds
       */
      public short loginRefreshMinPeriodSeconds() {
          return loginRefreshMinPeriodSeconds;
      }
  
      /**
       * The amount of buffer time before expiration to maintain when refreshing. If a
       * refresh is scheduled to occur closer to expiration than the number of seconds
       * defined here then the refresh will be moved up to maintain as much of the
       * desired buffer as possible.
       * 
       * @return the refresh buffer, in seconds
       */
      public short loginRefreshBufferSeconds() {
          return loginRefreshBufferSeconds;
      }
  
      /**
       * If the LoginModule and SaslClient implementations support multiple
       * simultaneous login contexts on a single Subject at the same time. If true,
       * then upon refresh, logout will only be invoked on the original LoginContext
       * after a new one successfully logs in. This can be helpful if the original
       * credential still has some lifetime left when an attempt to refresh the
       * credential fails; the client will still be able to create new connections as
       * long as the original credential remains valid. Otherwise, if logout is
       * immediately invoked prior to relogin, a relogin failure leaves the client
       * without the ability to connect until relogin does in fact succeed.
       * 
       * @return true if relogin is allowed prior to discarding an existing
       *         (presumably unexpired) credential, otherwise false
       */
      public boolean loginRefreshReloginAllowedBeforeLogout() {
          return loginRefreshReloginAllowedBeforeLogout;
      }
  }
  