diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt index 825ec11fd8..36aac3d1a8 100644 --- a/Documentation/dev-plugins.txt +++ b/Documentation/dev-plugins.txt @@ -497,9 +497,9 @@ $ ssh -p 29418 review.example.com sh ls $ ssh -p 29418 review.example.com sh ps ---- -[[configuration]] -Configuration -------------- +[[simple-configuration]] +Simple Configuration in `gerrit.config` +--------------------------------------- In Gerrit, global configuration is stored in the `gerrit.config` file. If a plugin needs global configuration, this configuration should be @@ -509,12 +509,12 @@ This approach of storing the plugin configuration is only suitable for plugins that have a simple configuration that only consists of key-value pairs. With this approach it is not possible to have subsections in the plugin configuration. Plugins that require a complex -configuration need to store their configuration in their own -configuration file where they can make use of subsections. On the other -hand storing the plugin configuration in a 'plugin' subsection in the -`gerrit.config` file has the advantage that administrators have all -configuration parameters in one file, instead of having one -configuration file per plugin. +configuration need to store their configuration in their +link:#configuration[own configuration file] where they can make use of +subsections. On the other hand storing the plugin configuration in a +'plugin' subsection in the `gerrit.config` file has the advantage that +administrators have all configuration parameters in one file, instead +of having one configuration file per plugin. To avoid conflicts with other plugins, it is recommended that plugins only use the `plugin` subsection with their own name. For example the @@ -541,6 +541,49 @@ String language = cfg.getFromGerritConfig("helloworld") .getString("language", "English"); ---- +[[configuration]] +Configuration in own config file +-------------------------------- + +Plugins can store their configuration in an own configuration file. +This makes sense if the plugin configuration is rather complex and +requires the usage of subsections. Plugins that have a simple +key-value pair configuration can store their configuration in a +link:#simple-configuration[`plugin` subsection of the `gerrit.config` +file]. + +The plugin configuration file must be named after the plugin and must +be located in the `etc` folder of the review site. For example a +configuration file for a `default-reviewer` plugin could look like +this: + +.$site_path/etc/default-reviewer.config +---- +[branch "refs/heads/master"] + reviewer = Project Owners + reviewer = john.doe@example.com +[match "file:^.*\.txt"] + reviewer = My Info Developers +---- + +Via the `com.google.gerrit.server.config.PluginConfigFactory` class a +plugin can easily access its configuration: + +[source,java] +---- +@Inject +private com.google.gerrit.server.config.PluginConfigFactory cfg; + +[...] + +String[] reviewers = cfg.getGlobalPluginConfig("default-reviewer") + .getStringList("branch", "refs/heads/master", "reviewer"); +---- + +The plugin configuration is loaded only once and is then cached. +Similar to changes in 'gerrit.config', changes to the plugin +configuration file will only become effective after a Gerrit restart. + [[project-specific-configuration]] Project Specific Configuration ------------------------------ diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java index 294d8a543b..e222bcf599 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java @@ -14,6 +14,7 @@ package com.google.gerrit.server.config; +import com.google.common.collect.Maps; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.project.NoSuchProjectException; import com.google.gerrit.server.project.ProjectCache; @@ -21,20 +22,36 @@ import com.google.gerrit.server.project.ProjectState; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.eclipse.jgit.util.FS; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Map; @Singleton public class PluginConfigFactory { + private static final Logger log = + LoggerFactory.getLogger(PluginConfigFactory.class); + + private final SitePaths site; private final Config cfg; private final ProjectCache projectCache; private final ProjectState.Factory projectStateFactory; + private final Map pluginConfigs; @Inject - PluginConfigFactory(@GerritServerConfig Config cfg, + PluginConfigFactory(SitePaths site, @GerritServerConfig Config cfg, ProjectCache projectCache, ProjectState.Factory projectStateFactory) { + this.site = site; this.cfg = cfg; this.projectCache = projectCache; this.projectStateFactory = projectStateFactory; + this.pluginConfigs = Maps.newHashMap(); } /** @@ -128,4 +145,38 @@ public class PluginConfigFactory { return getFromProjectConfig(projectName, pluginName).withInheritance( projectStateFactory); } + + /** + * Returns the configuration for the specified plugin that is stored in the + * plugin configuration file 'etc/.config'. + * + * The plugin configuration is only loaded once and is then cached. + * + * @param pluginName the name of the plugin for which the configuration should + * be returned + * @return the plugin configuration from the 'etc/.config' file + */ + public Config getGlobalPluginConfig(String pluginName) { + if (pluginConfigs.containsKey(pluginName)) { + return pluginConfigs.get(pluginName); + } + + File pluginConfigFile = new File(site.etc_dir, pluginName + ".config"); + FileBasedConfig cfg = new FileBasedConfig(pluginConfigFile, FS.DETECTED); + pluginConfigs.put(pluginName, cfg); + if (!cfg.getFile().exists()) { + log.info("No " + pluginConfigFile.getAbsolutePath() + "; assuming defaults"); + return cfg; + } + + try { + cfg.load(); + } catch (IOException e) { + log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e); + } catch (ConfigInvalidException e) { + log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e); + } + + return cfg; + } }