.classpath
| 1
dev-cli
| 1
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/DeployRecipeCommand.java
| 4
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/FileRecipeCommand.java
| 4
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RealizeRecipeCommand.java
| 74 +++
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeCommand.java
| 5
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
| 31 +
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
| 29 -
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
| 2
modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
| 10
modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
| 106 +++-
modules/plugins/filetemplate-bundle/src/test/java/org/rhq/plugins/filetemplate/ProcessingRecipeContextTest.java
| 225 ++++++++++
12 files changed, 450 insertions(+), 42 deletions(-)
New commits:
commit f7bb4c6924ea155514a7818223737aa89b2aaa04
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Mar 3 01:51:39 2010 -0500
add agent bundle plugin unit tests
diff --git a/.classpath b/.classpath
index c6a1ed2..fe06650 100644
--- a/.classpath
+++ b/.classpath
@@ -126,6 +126,7 @@
<classpathentry kind="src"
path="modules/plugins/augeas/src/main/java"/>
<classpathentry kind="src"
path="modules/plugins/augeas/src/test/java"/>
<classpathentry kind="src"
path="modules/plugins/filetemplate-bundle/src/main/java"/>
+ <classpathentry kind="src"
path="modules/plugins/filetemplate-bundle/src/test/java"/>
<classpathentry kind="src"
path="modules/helpers/rtfilter/src/main/java"/>
<classpathentry kind="src"
path="modules/helpers/pluginAnnotations/src/main/java"/>
<classpathentry kind="src"
path="modules/helpers/pluginGen/src/main/java"/>
diff --git
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
index ffe24f2..26199d3 100644
---
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
+++
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
@@ -34,6 +34,7 @@ import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.system.ProcessExecution;
import org.rhq.core.system.ProcessExecutionResults;
import org.rhq.core.system.SystemInfo;
+import org.rhq.core.util.file.FileUtil;
/**
* A recipe context that processes the recipe as it adds stuff to the context
@@ -61,7 +62,7 @@ public class ProcessingRecipeContext extends RecipeContext {
File existingFile = new File(this.baseWorkingDirectory, filename);
- ProcessExecution pe = getUnzipExecution(filename, directory);
+ ProcessExecution pe = getUnzipExecution(existingFile, directory);
if (pe != null) {
ProcessExecutionResults results = this.systemInfo.executeProcess(pe);
if (results.getError() != null) {
@@ -69,7 +70,7 @@ public class ProcessingRecipeContext extends RecipeContext {
} else if (results.getExitCode() == null || results.getExitCode().intValue()
> 0) {
throw new RuntimeException("Failed to unbundle file [" + pe +
"]: " + results);
}
- existingFile.delete();
+ // existingFile.delete(); WOULD WE WANT TO REMOVE THE COMPRESSED FILE?
} else {
// not a zipped format - just move the file to the directory as-is
File newFile = new File(directory, filename);
@@ -80,21 +81,27 @@ public class ProcessingRecipeContext extends RecipeContext {
}
@Override
- public void addFile(String filename, String directory) {
- super.addDeployFile(filename, directory);
+ public void addFile(String source, String destination) {
+ super.addFile(source, destination);
- File existingFile = new File(this.baseWorkingDirectory, filename);
- File newFile = new File(directory, filename);
- if (!existingFile.renameTo(newFile)) {
- throw new RuntimeException("Failed to move file [" + existingFile +
"] to [" + newFile + "]");
+ File sourceFile = new File(this.baseWorkingDirectory, source);
+ File destinationFile = new File(destination);
+
+ try {
+ destinationFile.getParentFile().mkdirs();
+ FileUtil.copyFile(sourceFile, destinationFile);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to copy file [" + sourceFile +
"] to [" + destinationFile + "]", e);
}
+
+ return;
}
@Override
public void addRealizedFile(String file) {
super.addRealizedFile(file);
- File trueFile = new File(file);
+ File trueFile = new File(this.baseWorkingDirectory, file);
RecipeParser parser = getParser();
File realizedTmpFile = null;
FileWriter realizedTmpFileWriter = null;
@@ -166,42 +173,44 @@ public class ProcessingRecipeContext extends RecipeContext {
}
}
- private ProcessExecution getUnzipExecution(String filename, String directory) {
+ private ProcessExecution getUnzipExecution(File file, String directory) {
String exe;
List<String> args = null;
- if (filename.endsWith(".tar")) {
+ String filepath = file.getAbsolutePath();
+
+ if (filepath.endsWith(".tar")) {
exe = "tar";
args = new ArrayList<String>();
args.add("xf");
- args.add(filename);
+ args.add(filepath);
args.add("-C");
args.add(directory);
- } else if (filename.endsWith(".tar.bz2") ||
filename.endsWith(".tbz2") || filename.endsWith(".tbz")) {
+ } else if (filepath.endsWith(".tar.bz2") ||
filepath.endsWith(".tbz2") || filepath.endsWith(".tbz")) {
exe = "tar";
args = new ArrayList<String>();
args.add("xfj");
- args.add(filename);
+ args.add(filepath);
args.add("-C");
args.add(directory);
- } else if (filename.endsWith(".tar.gz") ||
filename.endsWith(".tgz")) {
+ } else if (filepath.endsWith(".tar.gz") ||
filepath.endsWith(".tgz")) {
exe = "tar";
args = new ArrayList<String>();
args.add("xfz");
- args.add(filename);
+ args.add(filepath);
args.add("-C");
args.add(directory);
- } else if (filename.endsWith(".zip")) {
+ } else if (filepath.endsWith(".zip")) {
exe = "unzip";
args = new ArrayList<String>();
- args.add(filename);
+ args.add(filepath);
args.add("-d");
args.add(directory);
- } else if (filename.endsWith(".rpm")) {
+ } else if (filepath.endsWith(".rpm")) {
exe = "rpm";
args = new ArrayList<String>();
args.add("-i");
- args.add(filename);
+ args.add(filepath);
if (directory != null && directory.length() > 0) {
args.add("--prefix");
args.add(directory);
@@ -213,6 +222,7 @@ public class ProcessingRecipeContext extends RecipeContext {
ProcessExecution pe = new ProcessExecution(exe);
pe.setArguments(args);
pe.setWaitForCompletion(30 * 60 * 1000L);
+ pe.setCheckExecutableExists(false);
pe.setWorkingDirectory(this.baseWorkingDirectory);
return pe;
}
diff --git
a/modules/plugins/filetemplate-bundle/src/test/java/org/rhq/plugins/filetemplate/ProcessingRecipeContextTest.java
b/modules/plugins/filetemplate-bundle/src/test/java/org/rhq/plugins/filetemplate/ProcessingRecipeContextTest.java
new file mode 100644
index 0000000..1099481
--- /dev/null
+++
b/modules/plugins/filetemplate-bundle/src/test/java/org/rhq/plugins/filetemplate/ProcessingRecipeContextTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.plugins.filetemplate;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.bundle.filetemplate.recipe.RecipeContext;
+import org.rhq.bundle.filetemplate.recipe.RecipeParser;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.pluginapi.util.FileUtils;
+import org.rhq.core.system.SystemInfo;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.stream.StreamUtil;
+
+@Test
+public class ProcessingRecipeContextTest {
+ private StringBuilder recipe;
+
+ @BeforeMethod
+ public void cleanRecipeBeforeMethod() {
+ cleanRecipe();
+ }
+
+ @AfterClass
+ public void afterClass() throws IOException {
+ FileUtils.purge(getTmpDir(), true);
+ }
+
+ public void testRealizeRecipe() throws Exception {
+ File testDir = getTestDir("testrealize");
+ File file = writeFile("a b c\nhello<% var %>world\na b c\n",
testDir, "config.txt");
+
+ addRecipeCommand("realize --file=" + file.getName());
+
+ ProcessingRecipeContext context = createRecipeContext(testDir);
+ context.addReplacementVariableValue("var", "BOO");
+ context = parseRecipeNow(context);
+
+ Set<String> files = context.getRealizedFiles();
+ assert files.size() == 1 : files;
+ assert files.contains(file.getName()) : files;
+
+ String realizedContent = readFile(file);
+ assert realizedContent.equals("a b c\nhelloBOOworld\na b c\n") :
realizedContent;
+ }
+
+ public void testFileRecipe() throws Exception {
+ File testDir = getTestDir("testfile");
+ File testDestDir = getTestDir("testfile-dest");
+ File runme = writeFile("runme script", testDir,
"run-me.sh");
+ File runmeDest = new File(testDestDir, "run-me.sh");
+ File another = writeFile("<wotgorilla/>", testDir,
"META-INF/another.xml");
+ File anotherDest = new File(testDestDir, "/OTHER/another.xml");
+
+ addRecipeCommand("file --source=run-me.sh \"--destination=" +
runmeDest + "\"");
+ addRecipeCommand("file -s META-INF/another.xml -d \"" +
anotherDest + "\"");
+
+ RecipeContext context = parseRecipeNow(testDir);
+
+ Map<String, String> files = context.getFiles();
+ assert files.size() == 2 : files;
+ assert files.get("run-me.sh") != null : files;
+ assert files.get("run-me.sh").equals(runmeDest.getPath()) : files;
+ assert files.get("META-INF/another.xml") != null : files;
+ assert files.get("META-INF/another.xml").equals(anotherDest.getPath())
: files;
+
+ String runmeContent = readFile(runme);
+ String runmeDestContent = readFile(runmeDest);
+ assert runmeContent.equals(runmeDestContent) : runmeDestContent;
+ String anotherContent = readFile(another);
+ String anotherDestContent = readFile(anotherDest);
+ assert anotherContent.equals(anotherDestContent) : anotherDestContent;
+ }
+
+ public void testDeployRecipe() throws Exception {
+ File testDir = getTestDir("testdeploy");
+ File testDestDir = getTestDir("testdeploy-dest");
+ File unzippedFile = new File(testDestDir, "zipped-file.txt");
+ File zipFile = createZip("zipped file content", testDir,
"deploy-test.zip", unzippedFile.getName());
+
+ addRecipeCommand("deploy -f " + zipFile.getName() + " -d
\"" + testDestDir + "\"");
+
+ RecipeContext context = parseRecipeNow(testDir);
+
+ Map<String, String> files = context.getDeployFiles();
+ assert files.size() == 1 : files;
+ assert files.get(zipFile.getName()) != null;
+
+ String zippedFileContent = readFile(unzippedFile);
+ assert zippedFileContent.equals("zipped file content");
+ }
+
+ @Test(enabled = false)
+ public void testScriptRecipe() throws Exception {
+ File testDir = getTestDir("testscript");
+
+ addRecipeCommand("script echo hello");
+
+ RecipeContext context = parseRecipeNow(testDir);
+
+ Set<String> scripts = context.getScriptFiles();
+ assert scripts.size() == 1 : scripts;
+ assert scripts.contains("run-me.sh") : scripts;
+ assert scripts.contains("lots-o-params.sh") : scripts;
+ }
+
+ private ProcessingRecipeContext parseRecipeNow(File testDir) throws Exception {
+ ProcessingRecipeContext context = createRecipeContext(testDir);
+ return parseRecipeNow(context);
+ }
+
+ private ProcessingRecipeContext createRecipeContext(File testDir) {
+ Map<PackageVersion, File> packageVersionFiles = null; // TODO not used yet
+ SystemInfo sysinfo = SystemInfoFactory.createSystemInfo();
+ String cwd = testDir.getAbsolutePath();
+ ProcessingRecipeContext context = new ProcessingRecipeContext(getRecipe(),
packageVersionFiles, sysinfo, cwd);
+ return context;
+ }
+
+ private ProcessingRecipeContext parseRecipeNow(ProcessingRecipeContext context)
throws Exception {
+ RecipeParser parser = new RecipeParser();
+ parser.setReplaceReplacementVariables(true);
+ parser.parseRecipe(context);
+ return context;
+ }
+
+ private File getTestDir(String subdir) {
+ return new File(getTmpDir(), subdir);
+ }
+
+ private File getTmpDir() {
+ File tmpdir = new File(System.getProperty("java.io.tmpdir"),
"processing-recipe-test");
+ tmpdir.mkdirs();
+ return tmpdir;
+ }
+
+ private void cleanRecipe() {
+ this.recipe = new StringBuilder();
+ }
+
+ private void addRecipeCommand(String commandLine) {
+ this.recipe.append(commandLine).append("\n");
+ }
+
+ private String getRecipe() {
+ return this.recipe.toString();
+ }
+
+ private String readFile(File file) throws Exception {
+ return new String(StreamUtil.slurp(new FileInputStream(file)));
+ }
+
+ private File writeFile(String content, File destDir, String fileName) throws
Exception {
+ FileOutputStream out = null;
+
+ try {
+ File destFile = new File(destDir, fileName);
+ destFile.getParentFile().mkdirs();
+ out = new FileOutputStream(destFile);
+ out.write(content.getBytes());
+ return destFile;
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ }
+
+ private File createZip(String content, File destDir, String zipName, String
entryName) throws Exception {
+ FileOutputStream stream = null;
+ ZipOutputStream out = null;
+
+ try {
+ destDir.mkdirs();
+ File zipFile = new File(destDir, zipName);
+ stream = new FileOutputStream(zipFile);
+ out = new ZipOutputStream(stream);
+
+ ZipEntry zipAdd = new ZipEntry(entryName);
+ zipAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(zipAdd);
+ out.write(content.getBytes());
+ return zipFile;
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+}
commit 150fa0766fb19d1fc6d7ce9918df5fab6848219e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Mar 3 01:50:55 2010 -0500
remove this broken link
diff --git a/dev-cli b/dev-cli
deleted file mode 120000
index 9e0363b..0000000
--- a/dev-cli
+++ /dev/null
@@ -1 +0,0 @@
-modules/enterprise/remoting/cli/target/rhq-remoting-cli-1.4.0-SNAPSHOT
\ No newline at end of file
commit 981a3c4c5c77774b62e1b4e37f6b341aea1e1f35
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Mar 2 20:30:39 2010 -0500
add realize recipe command
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/DeployRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/DeployRecipeCommand.java
index 5f14f2f..d73f871 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/DeployRecipeCommand.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/DeployRecipeCommand.java
@@ -32,7 +32,7 @@ public class DeployRecipeCommand implements RecipeCommand {
return "deploy";
}
- public void parse(RecipeContext context, String[] args) {
+ public void parse(RecipeParser parser, RecipeContext context, String[] args) {
String sopts = ":f:d:";
LongOpt[] lopts = { new LongOpt("file", LongOpt.REQUIRED_ARGUMENT,
null, 'f'),
new LongOpt("directory", LongOpt.REQUIRED_ARGUMENT, null,
'd') };
@@ -40,7 +40,7 @@ public class DeployRecipeCommand implements RecipeCommand {
String filename = null;
String directory = null;
- Getopt getopt = new Getopt(context.toString(), args, sopts, lopts);
+ Getopt getopt = new Getopt(getName(), args, sopts, lopts);
int code;
while ((code = getopt.getopt()) != -1) {
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/FileRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/FileRecipeCommand.java
index 3b74805..2984bab 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/FileRecipeCommand.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/FileRecipeCommand.java
@@ -32,7 +32,7 @@ public class FileRecipeCommand implements RecipeCommand {
return "file";
}
- public void parse(RecipeContext context, String[] args) {
+ public void parse(RecipeParser parser, RecipeContext context, String[] args) {
String sopts = ":s:d:";
LongOpt[] lopts = { new LongOpt("source", LongOpt.REQUIRED_ARGUMENT,
null, 's'),
new LongOpt("destination", LongOpt.REQUIRED_ARGUMENT, null,
'd') };
@@ -40,7 +40,7 @@ public class FileRecipeCommand implements RecipeCommand {
String source = null;
String destination = null;
- Getopt getopt = new Getopt(context.toString(), args, sopts, lopts);
+ Getopt getopt = new Getopt(getName(), args, sopts, lopts);
int code;
while ((code = getopt.getopt()) != -1) {
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RealizeRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RealizeRecipeCommand.java
new file mode 100644
index 0000000..b187ed8
--- /dev/null
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RealizeRecipeCommand.java
@@ -0,0 +1,74 @@
+/*
+ * 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 gnu.getopt.Getopt;
+import gnu.getopt.LongOpt;
+
+public class RealizeRecipeCommand implements RecipeCommand {
+
+ public String getName() {
+ return "realize";
+ }
+
+ public void parse(RecipeParser parser, RecipeContext context, String[] args) {
+ String sopts = ":f:";
+ LongOpt[] lopts = { new LongOpt("file", LongOpt.REQUIRED_ARGUMENT,
null, 'f') };
+
+ String file = null;
+
+ Getopt getopt = new Getopt(getName(), args, sopts, lopts);
+ int code;
+
+ while ((code = getopt.getopt()) != -1) {
+ switch (code) {
+ case ':':
+ case '?': {
+ throw new IllegalArgumentException("Bad recipe command.");
+ }
+
+ case 1: {
+ throw new IllegalArgumentException("Bad recipe command!");
+ }
+
+ case 'f': {
+ file = getopt.getOptarg();
+ break;
+ }
+
+ default: {
+ throw new IllegalArgumentException("Unexpected error in recipe
command");
+ }
+
+ }
+ }
+
+ if (file == null) {
+ throw new IllegalArgumentException("Did not specify the file to
realize");
+ }
+
+ context.addRealizedFile(file);
+ return;
+ }
+}
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeCommand.java
index 7cfa964..01c1da3 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeCommand.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeCommand.java
@@ -34,9 +34,10 @@ public interface RecipeCommand {
/**
* Parses this recipe command and optionally puts information in the context.
- *
+ *
+ * @param parser the parser that is invoking this command
* @param context information where the parser can store information regarding the
command that was processed
* @param args arguments passed to the command.
*/
- void parse(RecipeContext context, String[] args);
+ void parse(RecipeParser recipeParser, RecipeContext context, String[] args);
}
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 dcea274..cb76a80 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
@@ -34,15 +34,17 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
/**
- * Contains information that is gleened from a recipe after it is parsed.
+ * 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 final Map<String, String> deployFiles;
private final Map<String, String> files;
+ private final Set<String> realizedFiles;
private final Set<String> replacementVariables;
private Configuration replacementVariableValues;
private final List<Script> scripts;
@@ -51,11 +53,24 @@ public class RecipeContext {
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.scripts = new ArrayList<Script>();
}
/**
+ * 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;
+ }
+
+ /**
* The full recipe that this context represents.
*
* @return the actual recipe text
@@ -95,6 +110,20 @@ public class RecipeContext {
}
/**
+ * 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
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 13644e6..98f26f6 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
@@ -77,17 +77,22 @@ public class RecipeParser {
public void parseRecipe(RecipeContext context) throws Exception {
- BufferedReader recipeReader = new BufferedReader(new
StringReader(context.getRecipe()));
- String line = recipeReader.readLine();
- while (line != null) {
- parseRecipeCommandLine(context, line);
- line = recipeReader.readLine();
+ context.setParser(this);
+ try {
+ BufferedReader recipeReader = new BufferedReader(new
StringReader(context.getRecipe()));
+ String line = recipeReader.readLine();
+ while (line != null) {
+ parseRecipeCommandLine(context, line);
+ line = recipeReader.readLine();
+ }
+ } finally {
+ context.setParser(null);
}
return;
}
- public void parseRecipeCommandLine(RecipeContext context, String line) throws
Exception {
+ protected void parseRecipeCommandLine(RecipeContext context, String line) throws
Exception {
// ignore blank lines or comment lines that start with #
if (line == null || line.trim().length() == 0 || line.startsWith("#"))
{
return;
@@ -112,7 +117,7 @@ public class RecipeParser {
}
try {
- recipeCommand.parse(context, arguments);
+ recipeCommand.parse(this, context, arguments);
} catch (Exception e) {
throw new Exception("Error in recipe, line [" + line +
"]", e);
}
@@ -125,6 +130,7 @@ public class RecipeParser {
RecipeCommand[] knownCommands = new RecipeCommand[] { new ScriptRecipeCommand(),
//
new FileRecipeCommand(), //
+ new RealizeRecipeCommand(), //
new DeployRecipeCommand() //
};
@@ -156,14 +162,9 @@ public class RecipeParser {
return replacementVariables;
}
- protected String replaceReplacementVariables(RecipeContext context, String input) {
+ public String replaceReplacementVariables(RecipeContext context, String input) {
- // don't bother if we have no values to replace them with
Configuration replacementValues = context.getReplacementVariableValues();
- if (replacementValues == null) {
- return input;
- }
-
TemplateEngine templateEngine = null;
StringBuffer buffer = new StringBuffer();
Matcher matcher = this.replacementVariableDeclarationPattern.matcher(input);
@@ -172,7 +173,7 @@ public class RecipeParser {
Matcher nameMatcher = this.replacementVariableNamePattern.matcher(next);
if (nameMatcher.find()) {
String key = nameMatcher.group();
- String value = replacementValues.getSimpleValue(key, null);
+ String value = (replacementValues != null) ?
replacementValues.getSimpleValue(key, null) : null;
if (value == null) {
// our replacement values don't know how to replace the key, see
if our system info template engine can
if (templateEngine == null) {
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
index 2173c06..99a0c7c 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
@@ -32,7 +32,7 @@ public class ScriptRecipeCommand implements RecipeCommand {
return "script";
}
- public void parse(RecipeContext context, String[] args) {
+ public void parse(RecipeParser parser, RecipeContext context, String[] args) {
if (args == null || args.length == 0) {
throw new IllegalArgumentException("Missing the script command to
execute");
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 7d5abef..bfa58e6 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
@@ -40,6 +40,16 @@ public class RecipeParserTest {
cleanRecipe();
}
+ public void testRealizeRecipe() throws Exception {
+ addRecipeCommand("realize --file=<%opt.dir%>/config.ini");
+ RecipeParser parser = new RecipeParser();
+ RecipeContext context = new RecipeContext(getRecipe());
+ parser.parseRecipe(context);
+ Set<String> files = context.getRealizedFiles();
+ assert files.size() == 1 : files;
+ assert files.contains("<%opt.dir%>/config.ini") : files;
+ }
+
public void testFileRecipe() throws Exception {
addRecipeCommand("file --source=run-me.sh --destination=/opt/run.sh");
addRecipeCommand("file -s META-INF/another.xml -d /etc/another.xml");
diff --git
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
index b0ae578..ffe24f2 100644
---
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
+++
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
@@ -19,13 +19,17 @@
package org.rhq.plugins.filetemplate;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.rhq.bundle.filetemplate.recipe.RecipeContext;
+import org.rhq.bundle.filetemplate.recipe.RecipeParser;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.system.ProcessExecution;
import org.rhq.core.system.ProcessExecutionResults;
@@ -87,6 +91,60 @@ public class ProcessingRecipeContext extends RecipeContext {
}
@Override
+ public void addRealizedFile(String file) {
+ super.addRealizedFile(file);
+
+ File trueFile = new File(file);
+ RecipeParser parser = getParser();
+ File realizedTmpFile = null;
+ FileWriter realizedTmpFileWriter = null;
+ BufferedReader reader = null;
+
+ try {
+
+ realizedTmpFile = File.createTempFile("rhq-realize-",
".tmp", trueFile.getParentFile());
+ realizedTmpFileWriter = new FileWriter(realizedTmpFile);
+
+ reader = new BufferedReader(new FileReader(trueFile));
+ String line = reader.readLine();
+ while (line != null) {
+ line = parser.replaceReplacementVariables(this, line);
+ realizedTmpFileWriter.write(line);
+ realizedTmpFileWriter.write("\n");
+ line = reader.readLine();
+ }
+
+ realizedTmpFileWriter.close();
+ realizedTmpFileWriter = null;
+ reader.close();
+ reader = null;
+
+ trueFile.delete(); // remove the one with the replacement variables in it
+ if (!realizedTmpFile.renameTo(trueFile)) {
+ throw new RuntimeException("Failed to rename realized tmp file
[" + realizedTmpFile + "]");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot realize file [" + file +
"]", e);
+ } finally {
+ if (realizedTmpFileWriter != null) {
+ try {
+ realizedTmpFileWriter.close();
+ } catch (Exception e) {
+ }
+ }
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Exception e) {
+ }
+ }
+ if (realizedTmpFile != null && realizedTmpFile.exists()) {
+ realizedTmpFile.delete();
+ }
+ }
+ }
+
+ @Override
public void addReplacementVariables(Set<String> replacementVariables) {
super.addReplacementVariables(replacementVariables);
}