Line data Source code
1 : // Copyright (C) 2013 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.gerrit.server.project.ProjectCache.noSuchProject; 18 : 19 : import com.google.gerrit.entities.Project; 20 : import com.google.gerrit.server.plugins.Plugin; 21 : import com.google.gerrit.server.plugins.ReloadPluginListener; 22 : import com.google.gerrit.server.project.NoSuchProjectException; 23 : import com.google.gerrit.server.project.ProjectCache; 24 : import com.google.gerrit.server.project.ProjectLevelConfig; 25 : import com.google.gerrit.server.project.ProjectState; 26 : import com.google.gerrit.server.securestore.SecureStore; 27 : import com.google.inject.Inject; 28 : import com.google.inject.Provider; 29 : import com.google.inject.Singleton; 30 : import java.util.HashMap; 31 : import java.util.Map; 32 : import org.eclipse.jgit.lib.Config; 33 : 34 : @Singleton 35 : public class PluginConfigFactory implements ReloadPluginListener { 36 : private static final String EXTENSION = ".config"; 37 : 38 : private final GlobalPluginConfigProvider globalPluginConfigProvider; 39 : private final Provider<Config> cfgProvider; 40 : private final ProjectCache projectCache; 41 : private final ProjectState.Factory projectStateFactory; 42 : private final SecureStore secureStore; 43 : private final Map<String, Config> pluginConfigs; 44 : 45 : private volatile Config cfg; 46 : 47 : @Inject 48 : PluginConfigFactory( 49 : @GerritServerConfig Provider<Config> cfgProvider, 50 : GlobalPluginConfigProvider globalPluginConfigProvider, 51 : ProjectCache projectCache, 52 : ProjectState.Factory projectStateFactory, 53 150 : SecureStore secureStore) { 54 150 : this.globalPluginConfigProvider = globalPluginConfigProvider; 55 150 : this.cfgProvider = cfgProvider; 56 150 : this.projectCache = projectCache; 57 150 : this.projectStateFactory = projectStateFactory; 58 150 : this.secureStore = secureStore; 59 : 60 150 : this.pluginConfigs = new HashMap<>(); 61 150 : this.cfg = cfgProvider.get(); 62 150 : } 63 : 64 : /** 65 : * Returns the configuration for the specified plugin that is stored in the 'gerrit.config' file. 66 : * 67 : * <p>The returned plugin configuration provides access to all parameters of the 'gerrit.config' 68 : * file that are set in the 'plugin' subsection of the specified plugin. 69 : * 70 : * <p>E.g.: [plugin "my-plugin"] myKey = myValue 71 : * 72 : * @param pluginName the name of the plugin for which the configuration should be returned 73 : * @return the plugin configuration from the 'gerrit.config' file 74 : */ 75 : public PluginConfig getFromGerritConfig(String pluginName) { 76 1 : return getFromGerritConfig(pluginName, false); 77 : } 78 : 79 : /** 80 : * Returns the configuration for the specified plugin that is stored in the 'gerrit.config' file. 81 : * 82 : * <p>The returned plugin configuration provides access to all parameters of the 'gerrit.config' 83 : * file that are set in the 'plugin' subsection of the specified plugin. 84 : * 85 : * <p>E.g.: [plugin "my-plugin"] myKey = myValue 86 : * 87 : * @param pluginName the name of the plugin for which the configuration should be returned 88 : * @param refresh if <code>true</code> it is checked if the 'gerrit.config' file was modified and 89 : * if yes the Gerrit configuration is reloaded, if <code>false</code> the cached Gerrit 90 : * configuration is used 91 : * @return the plugin configuration from the 'gerrit.config' file 92 : */ 93 : public PluginConfig getFromGerritConfig(String pluginName, boolean refresh) { 94 1 : if (refresh) { 95 0 : if (secureStore.isOutdated()) { 96 0 : secureStore.reload(); 97 : } 98 0 : cfg = cfgProvider.get(); 99 : } 100 1 : return PluginConfig.createFromGerritConfig(pluginName, cfg); 101 : } 102 : 103 : /** 104 : * Returns the configuration for the specified plugin that is stored in the 'project.config' file 105 : * of the specified project. 106 : * 107 : * <p>The returned plugin configuration provides access to all parameters of the 'project.config' 108 : * file that are set in the 'plugin' subsection of the specified plugin. 109 : * 110 : * <p>E.g.: [plugin "my-plugin"] myKey = myValue 111 : * 112 : * @param projectName the name of the project for which the plugin configuration should be 113 : * returned 114 : * @param pluginName the name of the plugin for which the configuration should be returned 115 : * @return the plugin configuration from the 'project.config' file of the specified project 116 : * @throws NoSuchProjectException thrown if the specified project does not exist 117 : */ 118 : public PluginConfig getFromProjectConfig(Project.NameKey projectName, String pluginName) 119 : throws NoSuchProjectException { 120 1 : ProjectState projectState = 121 1 : projectCache.get(projectName).orElseThrow(noSuchProject(projectName)); 122 1 : return getFromProjectConfig(projectState, pluginName); 123 : } 124 : 125 : /** 126 : * Returns the configuration for the specified plugin that is stored in the 'project.config' file 127 : * of the specified project. 128 : * 129 : * <p>The returned plugin configuration provides access to all parameters of the 'project.config' 130 : * file that are set in the 'plugin' subsection of the specified plugin. 131 : * 132 : * <p>E.g.: [plugin "my-plugin"] myKey = myValue 133 : * 134 : * @param projectState the project for which the plugin configuration should be returned 135 : * @param pluginName the name of the plugin for which the configuration should be returned 136 : * @return the plugin configuration from the 'project.config' file of the specified project 137 : */ 138 : public PluginConfig getFromProjectConfig(ProjectState projectState, String pluginName) { 139 2 : return projectState.getPluginConfig(pluginName); 140 : } 141 : 142 : /** 143 : * Returns the configuration for the specified plugin that is stored in the 'project.config' file 144 : * of the specified project. Parameters which are not set in the 'project.config' of this project 145 : * are inherited from the parent project's 'project.config' files. 146 : * 147 : * <p>The returned plugin configuration provides access to all parameters of the 'project.config' 148 : * file that are set in the 'plugin' subsection of the specified plugin. 149 : * 150 : * <p>E.g.: child project: [plugin "my-plugin"] myKey = childValue 151 : * 152 : * <p>parent project: [plugin "my-plugin"] myKey = parentValue anotherKey = someValue 153 : * 154 : * <p>return: [plugin "my-plugin"] myKey = childValue anotherKey = someValue 155 : * 156 : * @param projectName the name of the project for which the plugin configuration should be 157 : * returned 158 : * @param pluginName the name of the plugin for which the configuration should be returned 159 : * @return the plugin configuration from the 'project.config' file of the specified project with 160 : * inherited non-set parameters from the parent projects 161 : * @throws NoSuchProjectException thrown if the specified project does not exist 162 : */ 163 : public PluginConfig getFromProjectConfigWithInheritance( 164 : Project.NameKey projectName, String pluginName) throws NoSuchProjectException { 165 1 : return getFromProjectConfig(projectName, pluginName).withInheritance(projectStateFactory); 166 : } 167 : 168 : /** 169 : * Returns the configuration for the specified plugin that is stored in the 'project.config' file 170 : * of the specified project. Parameters which are not set in the 'project.config' of this project 171 : * are inherited from the parent project's 'project.config' files. 172 : * 173 : * <p>The returned plugin configuration provides access to all parameters of the 'project.config' 174 : * file that are set in the 'plugin' subsection of the specified plugin. 175 : * 176 : * <p>E.g.: child project: [plugin "my-plugin"] myKey = childValue 177 : * 178 : * <p>parent project: [plugin "my-plugin"] myKey = parentValue anotherKey = someValue 179 : * 180 : * <p>return: [plugin "my-plugin"] myKey = childValue anotherKey = someValue 181 : * 182 : * @param projectState the project for which the plugin configuration should be returned 183 : * @param pluginName the name of the plugin for which the configuration should be returned 184 : * @return the plugin configuration from the 'project.config' file of the specified project with 185 : * inherited non-set parameters from the parent projects 186 : */ 187 : public PluginConfig getFromProjectConfigWithInheritance( 188 : ProjectState projectState, String pluginName) { 189 0 : return getFromProjectConfig(projectState, pluginName).withInheritance(projectStateFactory); 190 : } 191 : 192 : /** 193 : * Returns the configuration for the specified plugin that is stored in the plugin configuration 194 : * file '{@code etc/<plugin-name>.config}'. 195 : * 196 : * <p>The plugin configuration is only loaded once and is then cached. 197 : * 198 : * @param pluginName the name of the plugin for which the configuration should be returned 199 : * @return the plugin configuration from the '{@code etc/<plugin-name>.config}' file 200 : */ 201 : public synchronized Config getGlobalPluginConfig(String pluginName) { 202 1 : if (pluginConfigs.containsKey(pluginName)) { 203 1 : return pluginConfigs.get(pluginName); 204 : } 205 : 206 1 : Config cfg = globalPluginConfigProvider.get(pluginName); 207 1 : GlobalPluginConfig pluginConfig = new GlobalPluginConfig(pluginName, cfg, secureStore); 208 1 : pluginConfigs.put(pluginName, pluginConfig); 209 1 : return pluginConfig; 210 : } 211 : 212 : /** 213 : * Returns the configuration for the specified plugin that is stored in the '{@code 214 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 215 : * 216 : * @param projectName the name of the project for which the plugin configuration should be 217 : * returned 218 : * @param pluginName the name of the plugin for which the configuration should be returned 219 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 220 : * project 221 : * @throws NoSuchProjectException thrown if the specified project does not exist 222 : */ 223 : public Config getProjectPluginConfig(Project.NameKey projectName, String pluginName) 224 : throws NoSuchProjectException { 225 0 : return getPluginConfig(projectName, pluginName).get(); 226 : } 227 : 228 : /** 229 : * Returns the configuration for the specified plugin that is stored in the '{@code 230 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 231 : * 232 : * @param projectState the project for which the plugin configuration should be returned 233 : * @param pluginName the name of the plugin for which the configuration should be returned 234 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 235 : * project 236 : */ 237 : public Config getProjectPluginConfig(ProjectState projectState, String pluginName) { 238 0 : return projectState.getConfig(pluginName + EXTENSION).get(); 239 : } 240 : 241 : /** 242 : * Returns the configuration for the specified plugin that is stored in the '{@code 243 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 244 : * Parameters which are not set in the '{@code <plugin-name>.config}' of this project are 245 : * inherited from the parent project's '{@code <plugin-name>.config}' files. 246 : * 247 : * <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue 248 : * 249 : * <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue 250 : * 251 : * <p>return: [mySection "mySubsection"] myKey = childValue anotherKey = someValue 252 : * 253 : * @param projectName the name of the project for which the plugin configuration should be 254 : * returned 255 : * @param pluginName the name of the plugin for which the configuration should be returned 256 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 257 : * project with inheriting non-set parameters from the parent projects 258 : * @throws NoSuchProjectException thrown if the specified project does not exist 259 : */ 260 : public Config getProjectPluginConfigWithInheritance( 261 : Project.NameKey projectName, String pluginName) throws NoSuchProjectException { 262 1 : return getPluginConfig(projectName, pluginName).getWithInheritance(/* merge= */ false); 263 : } 264 : 265 : /** 266 : * Returns the configuration for the specified plugin that is stored in the '{@code 267 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 268 : * Parameters which are not set in the '{@code <plugin-name>.config}' of this project are 269 : * inherited from the parent project's '{@code <plugin-name>.config}' files. 270 : * 271 : * <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue 272 : * 273 : * <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue 274 : * 275 : * <p>return: [mySection "mySubsection"] myKey = childValue anotherKey = someValue 276 : * 277 : * @param projectState the project for which the plugin configuration should be returned 278 : * @param pluginName the name of the plugin for which the configuration should be returned 279 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 280 : * project with inheriting non-set parameters from the parent projects 281 : */ 282 : public Config getProjectPluginConfigWithInheritance( 283 : ProjectState projectState, String pluginName) { 284 0 : return projectState.getConfig(pluginName + EXTENSION).getWithInheritance(/* merge= */ false); 285 : } 286 : 287 : /** 288 : * Returns the configuration for the specified plugin that is stored in the '{@code 289 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 290 : * Parameters from the '{@code <plugin-name>.config}' of the parent project are appended to this 291 : * project's '{@code <plugin-name>.config}' files. 292 : * 293 : * <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue 294 : * 295 : * <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue 296 : * 297 : * <p>return: [mySection "mySubsection"] myKey = childValue myKey = parentValue anotherKey = 298 : * someValue 299 : * 300 : * @param projectName the name of the project for which the plugin configuration should be 301 : * returned 302 : * @param pluginName the name of the plugin for which the configuration should be returned 303 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 304 : * project with parameters from the parent projects appended to the project values 305 : * @throws NoSuchProjectException thrown if the specified project does not exist 306 : */ 307 : public Config getProjectPluginConfigWithMergedInheritance( 308 : Project.NameKey projectName, String pluginName) throws NoSuchProjectException { 309 0 : return getPluginConfig(projectName, pluginName).getWithInheritance(/* merge= */ true); 310 : } 311 : 312 : /** 313 : * Returns the configuration for the specified plugin that is stored in the '{@code 314 : * <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project. 315 : * Parameters from the '{@code <plugin-name>.config}' of the parent project are appended to this 316 : * project's '{@code <plugin-name>.config}' files. 317 : * 318 : * <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue 319 : * 320 : * <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue 321 : * 322 : * <p>return: [mySection "mySubsection"] myKey = childValue myKey = parentValue anotherKey = 323 : * someValue 324 : * 325 : * @param projectState the project for which the plugin configuration should be returned 326 : * @param pluginName the name of the plugin for which the configuration should be returned 327 : * @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified 328 : * project with inheriting non-set parameters from the parent projects 329 : */ 330 : public Config getProjectPluginConfigWithMergedInheritance( 331 : ProjectState projectState, String pluginName) { 332 0 : return projectState.getConfig(pluginName + EXTENSION).getWithInheritance(/* merge= */ true); 333 : } 334 : 335 : private ProjectLevelConfig getPluginConfig(Project.NameKey projectName, String pluginName) 336 : throws NoSuchProjectException { 337 1 : ProjectState projectState = 338 1 : projectCache.get(projectName).orElseThrow(noSuchProject(projectName)); 339 1 : return projectState.getConfig(pluginName + EXTENSION); 340 : } 341 : 342 : @Override 343 : public synchronized void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) { 344 1 : pluginConfigs.remove(oldPlugin.getName()); 345 1 : } 346 : }