blob: fc705ad2e5c397958edce0b8bd32a734a2ae36f6 [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed 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 com.googlesource.gerrit.plugins.its.base.workflow;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.GlobalRulesFileName;
import com.googlesource.gerrit.plugins.its.base.ItsPath;
import com.googlesource.gerrit.plugins.its.base.PluginRulesFileName;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Collection and matcher against {@link Rule}s. */
public class RuleBase {
private static final Logger log = LoggerFactory.getLogger(RuleBase.class);
/** The section for rules within rulebases */
private static final String RULE_SECTION = "rule";
/** The key for actions within rulebases */
private static final String ACTION_KEY = "action";
private final Path itsPath;
private final Rule.Factory ruleFactory;
private final Condition.Factory conditionFactory;
private final ActionRequest.Factory actionRequestFactory;
private final String globalRulesFileName;
private final String pluginRulesFileName;
private Collection<Rule> rules;
public interface Factory {
RuleBase create();
}
@Inject
public RuleBase(
@ItsPath Path itsPath,
Rule.Factory ruleFactory,
Condition.Factory conditionFactory,
ActionRequest.Factory actionRequestFactory,
@GlobalRulesFileName String globalRulesFileName,
@PluginRulesFileName String pluginRulesFileName) {
this.itsPath = itsPath;
this.ruleFactory = ruleFactory;
this.conditionFactory = conditionFactory;
this.actionRequestFactory = actionRequestFactory;
this.globalRulesFileName = globalRulesFileName;
this.pluginRulesFileName = pluginRulesFileName;
reloadRules();
}
/**
* Adds rules from a file to the RuleBase.
*
* <p>If the given file does not exist, it is silently ignored
*
* @param ruleFile File from which to read the rules
*/
private void addRulesFromFile(File ruleFile) {
if (ruleFile.exists()) {
FileBasedConfig cfg = new FileBasedConfig(ruleFile, FS.DETECTED);
try {
cfg.load();
} catch (IOException | ConfigInvalidException e) {
log.error("Invalid ITS action configuration", e);
return;
}
for (String subsection : cfg.getSubsections(RULE_SECTION)) {
Rule rule = ruleFactory.create(subsection);
for (String key : cfg.getNames(RULE_SECTION, subsection)) {
String[] values = cfg.getStringList(RULE_SECTION, subsection, key);
if (ACTION_KEY.equals(key)) {
addActions(rule, values);
} else {
addConditions(rule, key, values);
}
}
rules.add(rule);
}
}
}
private void addActions(Rule rule, String[] values) {
for (String value : values) {
rule.addActionRequest(actionRequestFactory.create(value));
}
}
private void addConditions(Rule rule, String key, String[] values) {
for (String value : values) {
rule.addCondition(conditionFactory.create(key, value));
}
}
/** Loads the rules for the RuleBase. */
private void reloadRules() {
rules = Lists.newArrayList();
// Add global rules
File globalRuleFile = itsPath.resolve(globalRulesFileName).toFile();
addRulesFromFile(globalRuleFile);
// Add its-specific rules
File itsSpecificRuleFile = itsPath.resolve(pluginRulesFileName).toFile();
addRulesFromFile(itsSpecificRuleFile);
if (!globalRuleFile.exists() && !itsSpecificRuleFile.exists()) {
log.warn(
"Neither global rule file {} nor Its specific rule file {} exist. Please configure rules.",
globalRuleFile,
itsSpecificRuleFile);
}
}
/**
* Gets the action requests for a set of properties.
*
* @param properties The properties to search actions for.
* @return Requests for the actions that should be fired.
*/
public Collection<ActionRequest> actionRequestsFor(Map<String, String> properties) {
Collection<ActionRequest> ret = Lists.newLinkedList();
for (Rule rule : rules) {
ret.addAll(rule.actionRequestsFor(properties));
}
return ret;
}
}