/*
* RHQ Management Platform
* Copyright (C) 2005-2010 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.bundle.filetemplate.recipe;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.util.updater.DeploymentProperties;
/**
* Contains information that is gleened from a recipe during and after it is parsed.
*
* @author John Mazzitelli
*/
public class RecipeContext {
private RecipeParser parser;
private final String recipe;
private boolean unknownRecipe;
private final DeploymentProperties deploymentProperties;
private final Map<String, String> deployFiles;
private final Map<String, String> files;
private final Set<String> realizedFiles;
private final Set<String> replacementVariables;
private final Map<String, String> replacementVariableDefaultValues;
private Configuration replacementVariableValues;
private final List<Script> scripts;
private final List<Command> commands;
public RecipeContext(String recipe) {
if (recipe == null) {
throw new IllegalArgumentException("recipe == null");
}
this.recipe = recipe;
this.deployFiles = new HashMap<String, String>();
this.files = new HashMap<String, String>();
this.realizedFiles = new HashSet<String>();
this.replacementVariables = new HashSet<String>();
this.replacementVariableDefaultValues = new HashMap<String, String>();
this.scripts = new ArrayList<Script>();
this.commands = new ArrayList<Command>();
this.deploymentProperties = new DeploymentProperties();
this.unknownRecipe = true; // will be false if the recipe at least looks like one we understand
}
/**
* If this context is currently in use by a parser, this will be the reference to that parser.
* @return parser currently using this context
*/
public RecipeParser getParser() {
return parser;
}
public void setParser(RecipeParser parser) {
this.parser = parser;
}
/**
* Returns true if the recipe content does not look like a valid type that can be at least attempted
* to be parsed. In other words, this returns true if the recipe does not look like a file template
* recipe. This returns false if it looks like its file template recipe (even though it may have
* syntax errors in it).
*
* @return flag to indicate if the recipe looks like it might be a file template recipe
*/
public boolean isUnknownRecipe() {
return unknownRecipe;
}
public void setUnknownRecipe(boolean unknownRecipe) {
this.unknownRecipe = unknownRecipe;
}
/**
* The full recipe that this context represents.
*
* @return the actual recipe text
*/
public String getRecipe() {
return this.recipe;
}
/**
* Returns the deployment properties as defined in the recipe.
*
* @return the deployment properties
*/
public DeploymentProperties getDeploymentProperties() {
return deploymentProperties;
}
/**
* Returns all the files that are to be deployed. The key is the bundle file's name, the
* value is the directory where the bundle is to be deployed to.
*
* @return map of all files to be deployed and the location where they are to be deployed
*/
public Map<String, String> getDeployFiles() {
return this.deployFiles;
}
public void addDeployFile(String filename, String directory) {
this.deployFiles.put(filename, directory);
}
/**
* Returns all the files that are strictly to be copied to some location.
* The key is the bundle file's name, the value is the full path and filename where
* the file should be copied to. No processing of these files will occur other than
* they are copied.
*
* @return map of all files to be deployed and the location where they are to be deployed
*/
public Map<String, String> getFiles() {
return this.files;
}
public void addFile(String source, String destination) {
this.files.put(source, destination);
}
/**
* Returns the pathnames of all files that are to be realized (meaning, those that should
* have replacement variables replaced).
*
* @return set of all realized files
*/
public Set<String> getRealizedFiles() {
return this.realizedFiles;
}
public void addRealizedFile(String file) {
this.realizedFiles.add(file);
}
/**
* The names of all replacement variables that are found in the recipe.
*
* @return the replacement variables
*/
public Set<String> getReplacementVariables() {
return this.replacementVariables;
}
public void addReplacementVariables(Set<String> replacementVariables) {
this.replacementVariables.addAll(replacementVariables);
}
/**
* If a replacement varaible is known to have a default value, call this
* to set that default value.
*
* @param replacementVariable the variable whose default is being set
* @param defaultValue the value of the default for the given replacement variable
*/
public void assignDefaultValueToReplacementVariable(String replacementVariable, String defaultValue) {
this.replacementVariableDefaultValues.put(replacementVariable, defaultValue);
}
/**
* Returns a map keyed on replacement variables whose values are the default
* values for the replacement variables. Note that not all replacement variables
* found in {@link #getReplacementVariables()} will have an associated entry
* in the returned map (that is, not all variables have a default value).
*
* @return the map of all known default values for replacement variables
*/
public Map<String, String> getReplacementVariableDefaultValues() {
return this.replacementVariableDefaultValues;
}
/**
* If known, the returned value will contain values that are to be used to replace
* replacement variables found in the recipe.
*
* @return the replacement variable values
*/
public Configuration getReplacementVariableValues() {
return this.replacementVariableValues;
}
public void setReplacementVariableValues(Configuration configuration) {
this.replacementVariableValues = configuration;
}
/**
* Adds the given name/value pair to the set of replacement variable values associated
* with this context.
*
* @param name
* @param value
*/
public void addReplacementVariableValue(String name, String value) {
Configuration values = getReplacementVariableValues();
if (values == null) {
values = new Configuration();
setReplacementVariableValues(values);
}
values.put(new PropertySimple(name, value));
}
/**
* Returns a set of all the names of scripts found in the recipe.
*
* @return script names
*/
public Set<String> getScriptFiles() {
Set<String> scriptFiles = new HashSet<String>();
for (Script script : this.scripts) {
scriptFiles.add(script.getExecutable());
}
return scriptFiles;
}
/**
* Adds a script that the recipe wants invoked.
*
* @param exe the script executable
* @param exeArgs the arguments to pass to the script
*/
public void addScript(String exe, List<String> exeArgs) {
this.scripts.add(new Script(exe, exeArgs));
}
class Script {
private final String exe;
private final List<String> args;
public Script(String exe, List<String> args) {
this.exe = exe;
this.args = args;
}
public String getExecutable() {
return exe;
}
public List<String> getArguments() {
return args;
}
}
/**
* Adds a command that the recipe wants invoked. This command refers to an existing
* executable or shell command.
*
* @param cmd the main executable that this command wants to execute
* @param exeArgs the arguments to pass to the command executable
*/
public void addCommand(String exe, List<String> exeArgs) {
this.commands.add(new Command(exe, exeArgs));
}
class Command {
private final String exe;
private final List<String> args;
public Command(String exe, List<String> args) {
this.exe = exe;
this.args = args;
}
public String getExecutable() {
return exe;
}
public List<String> getArguments() {
return args;
}
}
@Override
public String toString() {
StringBuilder str = new StringBuilder("RecipeContext:\n");
str.append("Deployment Properties: ").append(getDeploymentProperties()).append("\n");
str.append("Deploy Files: ").append(getDeployFiles()).append("\n");
str.append("Replacement Vars: ").append(getReplacementVariables()).append("\n");
str.append("Replacement Values: ");
Configuration values = getReplacementVariableValues();
if (values == null) {
str.append("<none>");
} else {
str.append(values.getProperties());
}
str.append("\n");
str.append("Replacement Default Values: ");
Map<String, String> defaults = getReplacementVariableDefaultValues();
if (defaults == null) {
str.append("<none>");
} else {
str.append(defaults);
}
str.append("\n");
str.append("Script Files: ").append(getScriptFiles()).append("\n");
for (Script script : this.scripts) {
str.append("* ").append(script.getExecutable()).append(" ").append(script.getArguments()).append("\n");
}
str.append("Commands: ").append("\n");
for (Command cmd : this.commands) {
str.append("* ").append(cmd.getExecutable()).append(" ").append(cmd.getArguments()).append("\n");
}
str.append("Recipe Text:\n-----------\n").append(getRecipe()).append("\n");
return str.toString();
}
}