modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
| 7 +
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
| 38 +++---
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
| 37 ++++++
modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
| 59 ++++++++--
modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
| 18 ++-
5 files changed, 128 insertions(+), 31 deletions(-)
New commits:
commit dd4632701533ece8302da44595ef1dc6c2a1fdd4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 1 17:12:54 2010 -0500
start parsing replacement variables
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
index 029222b..26d1b82 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
@@ -26,6 +26,10 @@ package org.rhq.bundle.filetemplate.recipe;
import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
+/**
+ * @deprecated I think this command will not be used - probably should delete it
+ * @author mazz
+ */
public class ConfigdefRecipeCommand implements RecipeCommand {
public String getName() {
@@ -67,7 +71,8 @@ public class ConfigdefRecipeCommand implements RecipeCommand {
throw new IllegalArgumentException("Missing the -f argument to indicate
what the config def filename is");
}
- context.setConfigurationDefinitionFilename(filename);
+ // TODO: what to do? can I delete this command entirely?
+
return;
}
}
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
index 92c204e..c895107 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
@@ -24,7 +24,9 @@
package org.rhq.bundle.filetemplate.recipe;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* Contains information that is gleened from a recipe after it is parsed.
@@ -34,13 +36,13 @@ import java.util.Map;
public class RecipeContext {
private final String recipe;
- private String configurationDefinitionFilename;
- private Map<String, String> deployFiles;
+ private final Map<String, String> deployFiles;
+ private final Set<String> replacementVariables;
public RecipeContext(String recipe) {
this.recipe = recipe;
- this.configurationDefinitionFilename = null;
this.deployFiles = new HashMap<String, String>();
+ this.replacementVariables = new HashSet<String>();
}
/**
@@ -49,21 +51,7 @@ public class RecipeContext {
* @return the actual recipe text
*/
public String getRecipe() {
- return recipe;
- }
-
- /**
- * A recipe can have an optional configuration definition file associated with it.
- * If this returns non-<code>null</code>, it refers to this configuration
definition file.
- *
- * @return config def filename
- */
- public String getConfigurationDefinitionFilename() {
- return configurationDefinitionFilename;
- }
-
- public void setConfigurationDefinitionFilename(String filename) {
- this.configurationDefinitionFilename = filename;
+ return this.recipe;
}
/**
@@ -79,4 +67,18 @@ public class RecipeContext {
public void addDeployFile(String filename, String directory) {
this.deployFiles.put(filename, directory);
}
+
+ /**
+ * 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);
+ }
+
}
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
index b52e807..df797f4 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
@@ -30,8 +30,12 @@ import java.io.StreamTokenizer;
import java.io.StringReader;
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 java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Parses the file template recipe.
@@ -42,6 +46,12 @@ import java.util.Map;
public class RecipeParser {
private Map<String, RecipeCommand> recipeCommands;
+ // note that we use the same as the core util's template engine
+ // the native system replacement variable prefix is used by the agent-side fact
variable names
+ private final Pattern replacementVariableDeclarationPattern =
Pattern.compile("<%\\s*(\\w+\\.?)+\\s*%>");
+ private final Pattern replacementVariableNamePattern =
Pattern.compile("(\\w+\\.?)+");
+ private final String systemReplacementVariablePrefix = "rhq.system.";
+
public RecipeParser() {
setupRecipeCommands();
}
@@ -74,7 +84,13 @@ public class RecipeParser {
throw new Exception("Unknown command in recipe: " + commandName);
}
+ Set<String> replacementVars = getReplacementVariables(line);
+ if (replacementVars != null) {
+ context.addReplacementVariables(replacementVars);
+ }
+
recipeCommand.parse(context, arguments);
+
return;
}
@@ -90,6 +106,27 @@ public class RecipeParser {
}
}
+ private Set<String> getReplacementVariables(String cmdLine) {
+ Set<String> replacementVariables = null;
+ Matcher matcher = this.replacementVariableDeclarationPattern.matcher(cmdLine);
+ while (matcher.find()) {
+ String replacementDeclaration = matcher.group();
+ Matcher matcherInner =
this.replacementVariableNamePattern.matcher(replacementDeclaration);
+ if (!matcherInner.find()) {
+ throw new IllegalArgumentException("Bad replacement declaration
[" + replacementDeclaration + "]");
+ }
+ String replacementVariable = matcherInner.group();
+ if (!replacementVariable.startsWith(this.systemReplacementVariablePrefix)) {
+ if (replacementVariables == null) {
+ replacementVariables = new HashSet<String>(1);
+ }
+ replacementVariables.add(replacementVariable);
+ }
+ }
+
+ return replacementVariables;
+ }
+
private String[] splitCommandLine(String cmdLine) {
ByteArrayInputStream in = new ByteArrayInputStream(cmdLine.getBytes());
StreamTokenizer strtok = new StreamTokenizer(new InputStreamReader(in));
diff --git
a/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
b/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
index d573072..7d58b88 100644
---
a/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
+++
b/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
@@ -23,6 +23,8 @@
package org.rhq.bundle.filetemplate.recipe;
+import java.util.Map;
+
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -35,14 +37,49 @@ public class RecipeParserTest {
cleanRecipe();
}
+ public void testSimpleRecipeReplacementVariables() throws Exception {
+ addRecipeCommand("# <% ignored.inside.comment %>");
+ addRecipeCommand("deploy -f jboss.tar -d \"<% opt.dir
%>/jboss\"");
+ addRecipeCommand("deploy -f tomcat.tar -d <%opt.dir%>/tomcat");
+ addRecipeCommand("deploy -f jboss.zip -d
<%rhq.system.hostname%>/opt/tomcat"); // this is ignored, its an agent fact
variable
+ RecipeParser parser = new RecipeParser();
+ RecipeContext context = parser.parseRecipe(getRecipe());
+ Map<String, String> files = context.getDeployFiles();
+ assert files.containsKey("jboss.tar") : files;
+ assert files.get("jboss.tar").equals("<% opt.dir
%>/jboss") : files;
+ assert files.containsKey("tomcat.tar") : files;
+ assert
files.get("tomcat.tar").equals("<%opt.dir%>/tomcat") : files;
+ assert files.containsKey("jboss.zip") : files;
+ assert
files.get("jboss.zip").equals("<%rhq.system.hostname%>/opt/tomcat")
: files;
+ assert context.getReplacementVariables().contains("opt.dir") :
context.getReplacementVariables();
+ assert context.getReplacementVariables().size() == 1 :
context.getReplacementVariables();
+ }
+
public void testSimpleRecipe() throws Exception {
addRecipeCommand("deploy -f jboss.tar -d /opt/jboss");
- addRecipeCommand("configdef -f config.xml");
+ addRecipeCommand("deploy -f tomcat.tar -d /opt/tomcat");
+ RecipeParser parser = new RecipeParser();
+ RecipeContext context = parser.parseRecipe(getRecipe());
+ Map<String, String> files = context.getDeployFiles();
+ assert files.containsKey("jboss.tar") : files;
+ assert files.get("jboss.tar").equals("/opt/jboss") : files;
+ assert files.containsKey("tomcat.tar") : files;
+ assert files.get("tomcat.tar").equals("/opt/tomcat") :
files;
+ }
+
+ public void testSimpleRecipeWithQuotes() throws Exception {
+ addRecipeCommand("deploy -f jboss1.zip -d \"/opt/jboss1\"");
+ addRecipeCommand("deploy -f jboss.tar
--directory='/opt/jboss'");
+ addRecipeCommand("deploy -f tomcat.tar
\"--directory=/opt/tomcat\"");
RecipeParser parser = new RecipeParser();
RecipeContext context = parser.parseRecipe(getRecipe());
- assert
context.getConfigurationDefinitionFilename().equals("config.xml");
- assert context.getDeployFiles().containsKey("jboss.tar");
- assert
context.getDeployFiles().get("jboss.tar").equals("/opt/jboss");
+ Map<String, String> files = context.getDeployFiles();
+ assert files.containsKey("jboss1.zip") : files;
+ assert files.get("jboss1.zip").equals("/opt/jboss1") :
files;
+ assert files.containsKey("jboss.tar") : files;
+ assert files.get("jboss.tar").equals("'/opt/jboss'")
: files;
+ assert files.containsKey("tomcat.tar") : files;
+ assert files.get("tomcat.tar").equals("/opt/tomcat") :
files;
}
public void testSimpleRecipeError() throws Exception {
@@ -57,11 +94,11 @@ public class RecipeParserTest {
}
cleanRecipe();
- addRecipeCommand("configdef");
+ addRecipeCommand("deploy -d /opt/jboss");
try {
parser.parseRecipe(getRecipe());
- assert false : "This should have failed - need to provide a -f to the
configdef command";
+ assert false : "This should have failed - need to provide a -f to the
deploy command";
} catch (Exception ok) {
// to be expected
}
@@ -75,16 +112,18 @@ public class RecipeParserTest {
addRecipeCommand("");
addRecipeCommand("#");
addRecipeCommand("### comment here");
- addRecipeCommand("configdef -f config.xml");
+ addRecipeCommand("deploy -f tomcat.tar -d /opt/tomcat");
addRecipeCommand("");
addRecipeCommand("#");
addRecipeCommand("### comment here");
addRecipeCommand("");
RecipeParser parser = new RecipeParser();
RecipeContext context = parser.parseRecipe(getRecipe());
- assert
context.getConfigurationDefinitionFilename().equals("config.xml");
- assert context.getDeployFiles().containsKey("jboss.tar");
- assert
context.getDeployFiles().get("jboss.tar").equals("/opt/jboss");
+ Map<String, String> files = context.getDeployFiles();
+ assert files.containsKey("jboss.tar") : files;
+ assert files.get("jboss.tar").equals("/opt/jboss") : files;
+ assert files.containsKey("tomcat.tar") : files;
+ assert files.get("tomcat.tar").equals("/opt/tomcat") :
files;
}
private void cleanRecipe() {
diff --git
a/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
b/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
index a67fc1a..147f2a5 100644
---
a/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
+++
b/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
@@ -19,6 +19,8 @@
package org.rhq.enterprise.server.plugins.filetemplate;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
@@ -29,6 +31,8 @@ import org.rhq.bundle.filetemplate.recipe.RecipeParser;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
import org.rhq.enterprise.server.bundle.RecipeParseResults;
import org.rhq.enterprise.server.plugin.pc.ControlFacet;
import org.rhq.enterprise.server.plugin.pc.ControlResults;
@@ -68,9 +72,19 @@ public class BundleServerPluginComponent implements
ServerPluginComponent, Bundl
RecipeParser parser = new RecipeParser();
RecipeContext parserContext = parser.parseRecipe(recipe);
- // TODO convert the context into the proper data that the parse results wants
+ Set<String> bundleFileNames = new HashSet<String>();
+ Map<String, String> deployFiles = deployFiles =
parserContext.getDeployFiles();
+ bundleFileNames.addAll(deployFiles.keySet());
+
ConfigurationDefinition configDef = null;
- Set<String> bundleFileNames = null;
+ if (parserContext.getReplacementVariables() != null) {
+ configDef = new ConfigurationDefinition("replacementVariables",
null);
+ for (String replacementVar : parserContext.getReplacementVariables()) {
+ PropertyDefinitionSimple prop = new
PropertyDefinitionSimple(replacementVar, null, false,
+ PropertySimpleType.STRING);
+ configDef.put(prop);
+ }
+ }
RecipeParseResults results = new RecipeParseResults(configDef, bundleFileNames);
return results;