LCOV - code coverage report
Current view: top level - server/config - PluginConfig.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 64 94 68.1 %
Date: 2022-11-19 15:00:39 Functions: 17 36 47.2 %

          Line data    Source code
       1             : // Copyright (C) 2020 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.config;
      16             : 
      17             : import static com.google.common.base.Preconditions.checkState;
      18             : 
      19             : import com.google.auto.value.AutoValue;
      20             : import com.google.common.annotations.VisibleForTesting;
      21             : import com.google.common.base.MoreObjects;
      22             : import com.google.common.base.Strings;
      23             : import com.google.common.collect.ImmutableMap;
      24             : import com.google.common.collect.Iterables;
      25             : import com.google.gerrit.common.Nullable;
      26             : import com.google.gerrit.entities.AccountGroup;
      27             : import com.google.gerrit.entities.CachedProjectConfig;
      28             : import com.google.gerrit.entities.GroupReference;
      29             : import com.google.gerrit.server.project.ProjectConfig;
      30             : import com.google.gerrit.server.project.ProjectState;
      31             : import java.util.Arrays;
      32             : import java.util.HashMap;
      33             : import java.util.List;
      34             : import java.util.Map;
      35             : import java.util.Optional;
      36             : import java.util.Set;
      37             : import org.eclipse.jgit.errors.ConfigInvalidException;
      38             : import org.eclipse.jgit.lib.Config;
      39             : 
      40             : @AutoValue
      41           4 : public abstract class PluginConfig {
      42             :   private static final String PLUGIN = "plugin";
      43             : 
      44             :   protected abstract String pluginName();
      45             : 
      46             :   protected abstract Config cfg();
      47             : 
      48             :   protected abstract Optional<CachedProjectConfig> projectConfig();
      49             : 
      50             :   /** Mappings parsed from {@code groups} files. */
      51             :   protected abstract ImmutableMap<AccountGroup.UUID, GroupReference> groupReferences();
      52             : 
      53             :   public static PluginConfig create(
      54             :       String pluginName, Config cfg, @Nullable CachedProjectConfig projectConfig) {
      55             :     ImmutableMap.Builder<AccountGroup.UUID, GroupReference> groupReferences =
      56           3 :         ImmutableMap.builder();
      57           3 :     if (projectConfig != null) {
      58           3 :       groupReferences.putAll(projectConfig.getGroups());
      59             :     }
      60           3 :     return new AutoValue_PluginConfig(
      61           3 :         pluginName, copyConfig(cfg), Optional.ofNullable(projectConfig), groupReferences.build());
      62             :   }
      63             : 
      64             :   public static PluginConfig createFromGerritConfig(String pluginName, Config cfg) {
      65             :     // There is no need to make a defensive copy here because this value won't be cached.
      66             :     // gerrit.config uses baseConfig's (a member of Config) which would also make defensive copies
      67             :     // fail.
      68           1 :     return new AutoValue_PluginConfig(pluginName, cfg, Optional.empty(), ImmutableMap.of());
      69             :   }
      70             : 
      71             :   PluginConfig withInheritance(ProjectState.Factory projectStateFactory) {
      72           1 :     checkState(projectConfig().isPresent(), "no project config provided");
      73             : 
      74           1 :     ProjectState state = projectStateFactory.create(projectConfig().get());
      75           1 :     ProjectState parent = Iterables.getFirst(state.parents(), null);
      76           1 :     if (parent == null) {
      77           1 :       return this;
      78             :     }
      79             : 
      80           1 :     Map<AccountGroup.UUID, GroupReference> groupReferences = new HashMap<>();
      81           1 :     groupReferences.putAll(groupReferences());
      82           1 :     PluginConfig parentPluginConfig =
      83           1 :         parent.getPluginConfig(pluginName()).withInheritance(projectStateFactory);
      84           1 :     Set<String> allNames = cfg().getNames(PLUGIN, pluginName());
      85           1 :     Config newCfg = copyConfig(cfg());
      86           1 :     for (String name : parentPluginConfig.cfg().getNames(PLUGIN, pluginName())) {
      87           1 :       if (!allNames.contains(name)) {
      88           1 :         List<String> values =
      89           1 :             Arrays.asList(parentPluginConfig.cfg().getStringList(PLUGIN, pluginName(), name));
      90           1 :         for (String value : values) {
      91           1 :           Optional<GroupReference> groupRef =
      92             :               parentPluginConfig
      93           1 :                   .projectConfig()
      94           1 :                   .get()
      95           1 :                   .getGroupByName(GroupReference.extractGroupName(value));
      96           1 :           if (groupRef.isPresent()) {
      97           1 :             groupReferences.putIfAbsent(groupRef.get().getUUID(), groupRef.get());
      98             :           }
      99           1 :         }
     100           1 :         newCfg.setStringList(PLUGIN, pluginName(), name, values);
     101             :       }
     102           1 :     }
     103           1 :     return new AutoValue_PluginConfig(
     104           1 :         pluginName(), newCfg, projectConfig(), ImmutableMap.copyOf(groupReferences));
     105             :   }
     106             : 
     107             :   private static Config copyConfig(Config cfg) {
     108           3 :     Config copiedCfg = new Config();
     109             :     try {
     110           3 :       copiedCfg.fromText(cfg.toText());
     111           0 :     } catch (ConfigInvalidException e) {
     112             :       // cannot happen
     113           0 :       throw new IllegalStateException(e);
     114           3 :     }
     115           3 :     return copiedCfg;
     116             :   }
     117             : 
     118             :   public String getString(String name) {
     119           3 :     return cfg().getString(PLUGIN, pluginName(), name);
     120             :   }
     121             : 
     122             :   public String getString(String name, String defaultValue) {
     123           1 :     if (defaultValue == null) {
     124           1 :       return cfg().getString(PLUGIN, pluginName(), name);
     125             :     }
     126           0 :     return MoreObjects.firstNonNull(cfg().getString(PLUGIN, pluginName(), name), defaultValue);
     127             :   }
     128             : 
     129             :   public String[] getStringList(String name) {
     130           1 :     return cfg().getStringList(PLUGIN, pluginName(), name);
     131             :   }
     132             : 
     133             :   public int getInt(String name, int defaultValue) {
     134           0 :     return cfg().getInt(PLUGIN, pluginName(), name, defaultValue);
     135             :   }
     136             : 
     137             :   public long getLong(String name, long defaultValue) {
     138           0 :     return cfg().getLong(PLUGIN, pluginName(), name, defaultValue);
     139             :   }
     140             : 
     141             :   public boolean getBoolean(String name, boolean defaultValue) {
     142           0 :     return cfg().getBoolean(PLUGIN, pluginName(), name, defaultValue);
     143             :   }
     144             : 
     145             :   public <T extends Enum<?>> T getEnum(String name, T defaultValue) {
     146           0 :     return cfg().getEnum(PLUGIN, pluginName(), name, defaultValue);
     147             :   }
     148             : 
     149             :   public <T extends Enum<?>> T getEnum(T[] all, String name, T defaultValue) {
     150           0 :     return cfg().getEnum(all, PLUGIN, pluginName(), name, defaultValue);
     151             :   }
     152             : 
     153             :   public Set<String> getNames() {
     154           1 :     return cfg().getNames(PLUGIN, pluginName(), true);
     155             :   }
     156             : 
     157             :   public Optional<GroupReference> getGroupReference(String name) {
     158           2 :     String exactName = GroupReference.extractGroupName(getString(name));
     159           2 :     return groupReferences().values().stream().filter(g -> g.getName().equals(exactName)).findAny();
     160             :   }
     161             : 
     162             :   /** Mutable representation of {@link PluginConfig}. Used for updates. */
     163             :   public static class Update {
     164             :     private final String pluginName;
     165             :     private Config cfg;
     166             :     private final Optional<ProjectConfig> projectConfig;
     167             : 
     168           3 :     public Update(String pluginName, Config cfg, Optional<ProjectConfig> projectConfig) {
     169           3 :       this.pluginName = pluginName;
     170           3 :       this.cfg = cfg;
     171           3 :       this.projectConfig = projectConfig;
     172           3 :     }
     173             : 
     174             :     @VisibleForTesting
     175             :     public static Update forTest(String pluginName, Config cfg) {
     176           0 :       return new Update(pluginName, cfg, Optional.empty());
     177             :     }
     178             : 
     179             :     public PluginConfig asPluginConfig() {
     180           0 :       return PluginConfig.create(
     181           0 :           pluginName, cfg, projectConfig.map(ProjectConfig::getCacheable).orElse(null));
     182             :     }
     183             : 
     184             :     public String getString(String name) {
     185           0 :       return cfg.getString(PLUGIN, pluginName, name);
     186             :     }
     187             : 
     188             :     public String getString(String name, String defaultValue) {
     189           0 :       if (defaultValue == null) {
     190           0 :         return cfg.getString(PLUGIN, pluginName, name);
     191             :       }
     192           0 :       return MoreObjects.firstNonNull(cfg.getString(PLUGIN, pluginName, name), defaultValue);
     193             :     }
     194             : 
     195             :     public String[] getStringList(String name) {
     196           0 :       return cfg.getStringList(PLUGIN, pluginName, name);
     197             :     }
     198             : 
     199             :     public int getInt(String name, int defaultValue) {
     200           0 :       return cfg.getInt(PLUGIN, pluginName, name, defaultValue);
     201             :     }
     202             : 
     203             :     public long getLong(String name, long defaultValue) {
     204           0 :       return cfg.getLong(PLUGIN, pluginName, name, defaultValue);
     205             :     }
     206             : 
     207             :     public boolean getBoolean(String name, boolean defaultValue) {
     208           0 :       return cfg.getBoolean(PLUGIN, pluginName, name, defaultValue);
     209             :     }
     210             : 
     211             :     public <T extends Enum<?>> T getEnum(String name, T defaultValue) {
     212           0 :       return cfg.getEnum(PLUGIN, pluginName, name, defaultValue);
     213             :     }
     214             : 
     215             :     public <T extends Enum<?>> T getEnum(T[] all, String name, T defaultValue) {
     216           0 :       return cfg.getEnum(all, PLUGIN, pluginName, name, defaultValue);
     217             :     }
     218             : 
     219             :     public Set<String> getNames() {
     220           0 :       return cfg.getNames(PLUGIN, pluginName, true);
     221             :     }
     222             : 
     223             :     public void setString(String name, String value) {
     224           2 :       if (Strings.isNullOrEmpty(value)) {
     225           0 :         cfg.unset(PLUGIN, pluginName, name);
     226             :       } else {
     227           2 :         cfg.setString(PLUGIN, pluginName, name, value);
     228             :       }
     229           2 :     }
     230             : 
     231             :     public void setStringList(String name, List<String> values) {
     232           1 :       if (values == null || values.isEmpty()) {
     233           0 :         cfg.unset(PLUGIN, pluginName, name);
     234             :       } else {
     235           1 :         cfg.setStringList(PLUGIN, pluginName, name, values);
     236             :       }
     237           1 :     }
     238             : 
     239             :     public void setInt(String name, int value) {
     240           0 :       cfg.setInt(PLUGIN, pluginName, name, value);
     241           0 :     }
     242             : 
     243             :     public void setLong(String name, long value) {
     244           0 :       cfg.setLong(PLUGIN, pluginName, name, value);
     245           0 :     }
     246             : 
     247             :     public void setBoolean(String name, boolean value) {
     248           1 :       cfg.setBoolean(PLUGIN, pluginName, name, value);
     249           1 :     }
     250             : 
     251             :     public <T extends Enum<?>> void setEnum(String name, T value) {
     252           0 :       cfg.setEnum(PLUGIN, pluginName, name, value);
     253           0 :     }
     254             : 
     255             :     public void unset(String name) {
     256           1 :       cfg.unset(PLUGIN, pluginName, name);
     257           1 :     }
     258             : 
     259             :     public void setGroupReference(String name, GroupReference value) {
     260           2 :       checkState(projectConfig.isPresent(), "no project config provided");
     261           2 :       GroupReference groupRef = projectConfig.get().resolve(value);
     262           2 :       setString(name, groupRef.toConfigValue());
     263           2 :     }
     264             :   }
     265             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750