/* * 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; import java.util.List; import java.util.Map; import com.thoughtworks.go.domain.ConfigErrors; import com.thoughtworks.go.domain.RunIfConfigs; import com.thoughtworks.go.domain.Task; import com.thoughtworks.go.domain.config.Arguments; import com.thoughtworks.go.service.TaskFactory; import com.thoughtworks.go.util.ArrayUtil; import org.apache.commons.lang.StringUtils; public abstract class AbstractTask implements Task { @ConfigSubtag(label = "RunIfs") protected RunIfConfigs runIfConfigs = new RunIfConfigs(); @ConfigSubtag(label = "OnCancel", optional = true) public OnCancelConfig onCancelConfig = OnCancelConfig.killAllChildProcess(); public static final String RUN_IF_CONFIGS_PASSED = "runIfConfigsPassed"; public static final String RUN_IF_CONFIGS_FAILED = "runIfConfigsFailed"; public static final String RUN_IF_CONFIGS_ANY = "runIfConfigsAny"; public static final String ON_CANCEL_CONFIG = "onCancelConfig"; public static final String HAS_CANCEL_TASK = "hasCancelTask"; protected ConfigErrors errors = new ConfigErrors(); public RunIfConfigs getConditions() { return runIfConfigs; } public void setConditions(RunIfConfigs runIfConfigs) { this.runIfConfigs = runIfConfigs; } public String getConditionsForDisplay() { if (runIfConfigs.isEmpty()) { return StringUtils.capitalize(RunIfConfig.PASSED.toString()); } Object[] conditions = ArrayUtil.capitalizeContents(runIfConfigs.toArray()); return ArrayUtil.join(conditions, ", "); } public Task cancelTask() { return onCancelConfig.getTask(); } public OnCancelConfig onCancelConfig() { return onCancelConfig; } public OnCancelConfig getOnCancelConfig() { return onCancelConfig; } public boolean hasCancelTask() { return onCancelConfig.hasCancelTask(); } public void setCancelTask(Task task) { this.onCancelConfig = new OnCancelConfig(task); } public void setOnCancelConfig(OnCancelConfig onCancelConfig) { this.onCancelConfig = onCancelConfig; } public boolean runIfConfigsPassed() { return runIfConfigs.match(RunIfConfig.PASSED); } public boolean runIfConfigsFailed() { return runIfConfigs.match(RunIfConfig.FAILED); } public boolean runIfConfigsAny() { return runIfConfigs.match(RunIfConfig.ANY); } public String describe() { // for #2398. sigh StringBuilder builder = new StringBuilder(); ConfigTag configTag = this.getClass().getAnnotation(ConfigTag.class); builder.append("<").append(configTag.value()).append(" "); GoConfigClassWriter cruiseConfigClass = new GoConfigClassWriter(this.getClass(), new ConfigCache(), null); List<GoConfigFieldWriter> fields = cruiseConfigClass.getAllFields(this); for (GoConfigFieldWriter field : fields) { if (field.isAttribute()) { Object value = field.getValue(); if (!field.isDefault(cruiseConfigClass)) { appendIfNotEmpty(builder, value, field.value()); } } else { addDescribeOfArguments(builder, configTag, field); } } if (!(this instanceof ExecTask)) { builder.append("/>"); } return builder.toString(); } private void addDescribeOfArguments(StringBuilder builder, ConfigTag configTag, GoConfigFieldWriter field) { if (field.isSubtag() && field.getValue() instanceof Arguments) { closeConfigTag(builder, field); if (field.getValue() instanceof Arguments && ((Arguments) field.getValue()).size() != 0) { for (Argument arg : (Arguments) field.getValue()) { builder.append(String.format("<arg>%s</arg>", arg.getValue())).append("\n"); } builder.append("</" + configTag.value() + ">"); } } } private void closeConfigTag(StringBuilder builder, GoConfigFieldWriter field) { if (((Arguments) field.getValue()).size() != 0) { builder.append(">").append("\n"); } else { builder.append("/>"); } } private void appendIfNotEmpty(StringBuilder builder, Object value, String description) { if (value != null && StringUtils.isNotBlank(value.toString())) { builder.append(String.format("%s=\"%s\" ", description, value)); } } public final void setConfigAttributes(Object attributes, TaskFactory taskFactory) { Map attributeMap = (Map) attributes; if (attributes == null || attributeMap.isEmpty()) { return; } runIfConfigs.clear(); if (attributeMap.containsKey(RUN_IF_CONFIGS_ANY) && "1".equals(attributeMap.get(RUN_IF_CONFIGS_ANY))) { runIfConfigs.add(RunIfConfig.ANY); } if (attributeMap.containsKey(RUN_IF_CONFIGS_FAILED) && "1".equals(attributeMap.get(RUN_IF_CONFIGS_FAILED))) { runIfConfigs.add(RunIfConfig.FAILED); } if (attributeMap.containsKey(RUN_IF_CONFIGS_PASSED) && "1".equals(attributeMap.get(RUN_IF_CONFIGS_PASSED))) { runIfConfigs.add(RunIfConfig.PASSED); } if ("1".equals(attributeMap.get(HAS_CANCEL_TASK))) { onCancelConfig = OnCancelConfig.create((Map) attributeMap.get(ON_CANCEL_CONFIG), taskFactory); } else if ("0".equals(attributeMap.get(HAS_CANCEL_TASK))) { onCancelConfig = OnCancelConfig.killAllChildProcess(); } setTaskConfigAttributes(attributeMap); } @Override public final void setConfigAttributes(Object attributes) { setConfigAttributes(attributes, null); } @Override public boolean hasSameTypeAs(Task task) { return this.getTaskType().equals(task.getTaskType()); } @Override public boolean validateTree(ValidationContext validationContext) { validate(validationContext); return onCancelConfig.validateTree(validationContext) && errors.isEmpty(); } protected abstract void setTaskConfigAttributes(Map attributes); public final void validate(ValidationContext validationContext) { validateTask(validationContext); validateNestedOnCancelTask(); } private void validateNestedOnCancelTask() { if (cancelTask().hasCancelTask()) { errors.add(ON_CANCEL_CONFIG, "Cannot nest 'oncancel' within a cancel task"); } } protected abstract void validateTask(ValidationContext validationContext); public final ConfigErrors errors() { return errors; } public void addError(String fieldName, String message) { errors.add(fieldName, message); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } AbstractTask that = (AbstractTask) o; if (onCancelConfig != null ? !onCancelConfig.equals(that.onCancelConfig) : that.onCancelConfig != null) { return false; } if (runIfConfigs != null ? !runIfConfigs.equals(that.runIfConfigs) : that.runIfConfigs != null) { return false; } return true; } @Override public int hashCode() { int result = runIfConfigs != null ? runIfConfigs.hashCode() : 0; result = 31 * result + (onCancelConfig != null ? onCancelConfig.hashCode() : 0); return result; } }