/*
* Copyright 2015 ThoughtWorks, Inc.
*
* 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.thoughtworks.go.config.pluggabletask;
import com.thoughtworks.go.config.AbstractTask;
import com.thoughtworks.go.config.ConfigSubtag;
import com.thoughtworks.go.config.ConfigTag;
import com.thoughtworks.go.config.ValidationContext;
import com.thoughtworks.go.config.builder.ConfigurationPropertyBuilder;
import com.thoughtworks.go.domain.Task;
import com.thoughtworks.go.domain.TaskProperty;
import com.thoughtworks.go.domain.config.Configuration;
import com.thoughtworks.go.domain.config.ConfigurationProperty;
import com.thoughtworks.go.domain.config.ConfigurationValue;
import com.thoughtworks.go.domain.config.PluginConfiguration;
import com.thoughtworks.go.plugin.access.pluggabletask.PluggableTaskConfigStore;
import com.thoughtworks.go.plugin.access.pluggabletask.TaskPreference;
import com.thoughtworks.go.plugin.api.config.Property;
import com.thoughtworks.go.plugin.api.task.TaskConfig;
import com.thoughtworks.go.plugin.api.task.TaskConfigProperty;
import com.thoughtworks.go.util.ListUtil;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @understands configuration of pluggable task
*/
@ConfigTag("task")
public class PluggableTask extends AbstractTask {
public static final String TYPE = "pluggable_task";
public static final String VALUE_KEY = "value";
public static final String ERRORS_KEY = "errors";
public static final String PLUGGABLE_TASK_PREFIX = TYPE;
@ConfigSubtag
private PluginConfiguration pluginConfiguration = new PluginConfiguration();
@ConfigSubtag
private Configuration configuration = new Configuration();
public PluggableTask() {
}
public PluggableTask(PluginConfiguration pluginConfiguration, Configuration configuration) {
this.pluginConfiguration = pluginConfiguration;
this.configuration = configuration;
}
public PluginConfiguration getPluginConfiguration() {
return pluginConfiguration;
}
public void setPluginConfiguration(PluginConfiguration pluginConfiguration) {
this.pluginConfiguration = pluginConfiguration;
}
public Configuration getConfiguration() {
return configuration;
}
@Override
public boolean hasSameTypeAs(Task task) {
if (!getClass().equals(task.getClass())) {
return false;
}
return this.pluginConfiguration.equals(((PluggableTask) task).pluginConfiguration);
}
@Override
protected void setTaskConfigAttributes(Map attributes) {
TaskConfig taskConfig = PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId()).getConfig();
for (Property property : taskConfig.list()) {
String key = property.getKey();
if (attributes.containsKey(key)) {
Boolean isSecure = property.getOption(Property.SECURE);
if (configuration.getProperty(key) == null) {
configuration.addNewConfiguration(property.getKey(), isSecure);
}
configuration.getProperty(key).setConfigurationValue(new ConfigurationValue((String) attributes.get(key)));
configuration.getProperty(key).handleSecureValueConfiguration(isSecure);
}
}
}
public TaskConfig toTaskConfig() {
TaskConfig taskConfig = new TaskConfig();
for (ConfigurationProperty configurationProperty : configuration) {
taskConfig.add(new TaskConfigProperty(configurationProperty.getConfigurationKey().getName(), configurationProperty.getValue()));
}
return taskConfig;
}
public void addConfigurations(List<ConfigurationProperty> configurations) {
ConfigurationPropertyBuilder builder = new ConfigurationPropertyBuilder();
for (ConfigurationProperty property : configurations) {
if(isValidPluginConfiguration(property.getConfigKeyName())) {
configuration.add(builder.create(property.getConfigKeyName(), property.getConfigValue(), property.getEncryptedValue(),
pluginConfigurationFor(property.getConfigKeyName()).getOption(Property.SECURE)));
} else {
configuration.add(property);
}
}
}
private boolean isValidPluginConfiguration(String configKey) {
return taskPreference() != null && pluginConfigurationFor(configKey) != null;
}
private Property pluginConfigurationFor(String configKey) {
TaskPreference taskPreference = taskPreference();
return taskPreference != null ? taskPreference.getConfig().get(configKey) : null;
}
private TaskPreference taskPreference() {
return PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId());
}
@PostConstruct
public void applyPluginMetadata() {
if (taskPreference() != null) {
for (ConfigurationProperty configurationProperty : configuration) {
if (isValidPluginConfiguration(configurationProperty.getConfigKeyName())) {
Boolean isSecure = pluginConfigurationFor(configurationProperty.getConfigKeyName()).getOption(Property.SECURE);
configurationProperty.handleSecureValueConfiguration(isSecure);
}
}
}
}
@Override
protected void validateTask(ValidationContext validationContext) {
}
@Override
public boolean validateTree(ValidationContext validationContext) {
validate(validationContext);
return (onCancelConfig.validateTree(validationContext) && errors.isEmpty() && !configuration.hasErrors());
}
// This method is called from PluggableTaskService to validate Tasks.
public boolean isValid() {
if (PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId()) == null) {
addError(TYPE, String.format("Could not find plugin for given pluggable id:[%s].", pluginConfiguration.getId()));
}
configuration.validateTree();
return (errors.isEmpty() && !configuration.hasErrors());
}
@Override
public String getTaskType() {
return PLUGGABLE_TASK_PREFIX + "_" + getPluginConfiguration().getId().replaceAll("[^a-zA-Z0-9_]", "_");
}
@Override
public String getTypeForDisplay() {
return "Pluggable Task";
}
@Override
public List<TaskProperty> getPropertiesForDisplay() {
ArrayList<TaskProperty> taskProperties = new ArrayList<>();
if (PluggableTaskConfigStore.store().hasPreferenceFor(pluginConfiguration.getId())) {
TaskPreference preference = taskPreference();
List<? extends Property> propertyDefinitions = preference.getConfig().list();
for (Property propertyDefinition : propertyDefinitions) {
ConfigurationProperty configuredProperty = configuration.getProperty(propertyDefinition.getKey());
if (configuredProperty == null) continue;
taskProperties.add(new TaskProperty(propertyDefinition.getOption(Property.DISPLAY_NAME), configuredProperty.getDisplayValue(), configuredProperty.getConfigKeyName()));
}
return taskProperties;
}
for (ConfigurationProperty property : configuration) {
taskProperties.add(new TaskProperty(property.getConfigKeyName(), property.getDisplayValue()));
}
return taskProperties;
}
public Map<String, Map<String, String>> configAsMap() {
Map<String, Map<String, String>> configMap = new HashMap<>();
for (ConfigurationProperty property : configuration) {
Map<String, String> mapValue = new HashMap<>();
mapValue.put(VALUE_KEY, property.getValue());
if (!property.errors().isEmpty()) {
mapValue.put(ERRORS_KEY, ListUtil.join(property.errors().getAll()));
}
configMap.put(property.getConfigKeyName(), mapValue);
}
return configMap;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
PluggableTask that = (PluggableTask) o;
if (configuration != null ? !configuration.equals(that.configuration) : that.configuration != null) {
return false;
}
if (!pluginConfiguration.equals(that.pluginConfiguration)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + pluginConfiguration.hashCode();
result = 31 * result + (configuration != null ? configuration.hashCode() : 0);
return result;
}
}