.classpath
| 5
modules/common/ant-bundle/pom.xml
| 50 +
modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AbstractBundleTask.java
| 27 +
modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AntLauncher.java
| 191 +++++++
modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleAntProject.java
| 50 +
modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleTask.java
| 29 +
modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/LoggerAntBuildListener.java
| 115 ++++
modules/common/ant-bundle/src/main/resources/bundle-ant-tasks.properties
| 1
modules/common/ant-bundle/src/test/java/org/rhq/bundle/ant/AntLauncherTest.java
| 87 +++
modules/common/ant-bundle/src/test/resources/simple-build.xml
| 12
modules/common/pom.xml
| 1
modules/core/util/src/main/java/org/rhq/core/template/TemplateEngine.java
| 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
| 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
| 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/bundle/BundleServerPluginManager.java
| 44 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
| 5
modules/enterprise/server/plugins/ant-bundle/pom.xml
| 214 ++++++++
modules/enterprise/server/plugins/ant-bundle/src/main/java/org/rhq/enterprise/server/plugins/ant/AntBundleServerPluginComponent.java
| 125 ++++
modules/enterprise/server/plugins/ant-bundle/src/main/resources/META-INF/rhq-serverplugin.xml
| 20
modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
| 6
modules/enterprise/server/plugins/pom.xml
| 1
modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
| 1
modules/plugins/ant-bundle/pom.xml
| 267 ++++++++++
modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
| 136 +++++
modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginDiscoveryComponent.java
| 51 +
modules/plugins/ant-bundle/src/main/resources/META-INF/rhq-plugin.xml
| 20
modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
| 158 +++++
modules/plugins/ant-bundle/src/test/resources/log4j.xml
| 35 +
modules/plugins/ant-bundle/src/test/resources/simple-build.xml
| 8
modules/plugins/ant-bundle/src/test/resources/test-build.xml
| 27 +
modules/plugins/pom.xml
| 1
modules/plugins/validate-all-plugins/pom.xml
| 1
32 files changed, 1689 insertions(+), 27 deletions(-)
New commits:
commit 8bd78f0b3a282f09d4549dee054d94855509d484
Merge: c3bb31e... ae88c7c...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 29 00:31:34 2010 -0400
Merge branch 'gwt' of
ssh://git.fedorahosted.org/git/rhq/rhq into gwt
commit c3bb31e179881380b02df5d9dee0743878a3e4c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 29 00:31:14 2010 -0400
introduce a new bundle type - ANT
we now two kinds of bundles - one has a simple recipe style (file template)
and the second uses Ant scripts as its recipe (thus providing a
more advanced way to lay down bundle content on the agent)
diff --git a/.classpath b/.classpath
index 082cf31..c1a9e78 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src"
path="modules/common/jboss-as/src/main/java"/>
+ <classpathentry kind="src"
path="modules/common/ant-bundle/src/main/java"/>
+ <classpathentry kind="src"
path="modules/common/ant-bundle/src/test/java"/>
<classpathentry kind="src"
path="modules/common/filetemplate-bundle/src/main/java"/>
<classpathentry kind="src"
path="modules/common/filetemplate-bundle/src/test/java"/>
<classpathentry kind="src"
path="modules/enterprise/gui/base-perspective-jar/src/main/java"/>
@@ -71,6 +73,7 @@
<classpathentry kind="src"
path="modules/enterprise/server/plugins/alert-microblog/src/main/java"/>
<classpathentry kind="src"
path="modules/enterprise/server/plugins/alert-mobicents/src/main/java"/>
<classpathentry kind="src"
path="modules/enterprise/server/plugins/cobbler/src/main/java"/>
+ <classpathentry kind="src"
path="modules/enterprise/server/plugins/ant-bundle/src/main/java"/>
<classpathentry kind="src"
path="modules/enterprise/server/plugins/filetemplate-bundle/src/main/java"/>
<classpathentry kind="src"
path="modules/enterprise/gui/portal-war/src/main/java"/>
<classpathentry kind="src"
path="modules/enterprise/gui/portal-war/src/test/java"/>
@@ -129,6 +132,8 @@
<classpathentry kind="src"
path="modules/plugins/jdbctrace/src/main/java"/>
<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/ant-bundle/src/main/java"/>
+ <classpathentry kind="src"
path="modules/plugins/ant-bundle/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"/>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
new file mode 100644
index 0000000..90e3f39
--- /dev/null
+++ b/modules/common/ant-bundle/pom.xml
@@ -0,0 +1,50 @@
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-common-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-ant-bundle-common</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Ant Bundle Plugins Common Library</name>
+ <description>A library with the code common to the agent and server plugins for
Ant Bundles</description>
+
+ <scm>
+
<
connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/comm...
+
<
developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/mod...
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/common/ant-bundle/</scm.module.path>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.6.5</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ <version>1.6.5</version>
+ </dependency>
+
+ <!-- include some optional ant tasks for users to be able to use -->
+ <dependency>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>1.0b3</version>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git
a/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AbstractBundleTask.java
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AbstractBundleTask.java
new file mode 100644
index 0000000..d5db4cc
--- /dev/null
+++ b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AbstractBundleTask.java
@@ -0,0 +1,27 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.bundle.ant;
+
+import org.apache.tools.ant.Task;
+
+public abstract class AbstractBundleTask extends Task {
+ public BundleAntProject getBundleAntProject() {
+ return (BundleAntProject) getProject();
+ }
+}
\ No newline at end of file
diff --git a/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AntLauncher.java
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AntLauncher.java
new file mode 100644
index 0000000..b184274
--- /dev/null
+++ b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/AntLauncher.java
@@ -0,0 +1,191 @@
+/*
+ * 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.ant;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.helper.ProjectHelper2;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+
+public class AntLauncher {
+
+ // currently, the bundle plugins don't need custom ant tasks, but there is an ant
task stubbed for future use here
+ private static final String ANT_TASKS = "bundle-ant-tasks.properties";
+
+ /**
+ * Launches ANT and parses the given build file and optionally executes it.
+ *
+ * @param buildFile the build file that ANT will run
+ * @param target the target to run, <code>null</code> will run
the default target
+ * @param customTaskDefs the properties file found in classloader that contains all
the taskdef definitions
+ * @param properties set of properties to set for the ANT task to access
+ * @param logFile where ANT messages will be logged
+ * @param logStdOut if <code>true</code>, log messages will be sent
to stdout as well as the log file
+ * @param execute if <code>true</code> the ant script will be
parsed and executed; otherwise, it will only be parsed
+ *
+ * @throws RuntimeException
+ */
+ public BundleAntProject startAnt(File buildFile, String target, String
customTaskDefs, Properties properties,
+ File logFile, boolean logStdOut, boolean execute) {
+
+ PrintWriter logFileOutput = null;
+
+ try {
+ logFileOutput = new PrintWriter(new FileOutputStream(logFile, true));
+
+ ClassLoader classLoader = getClass().getClassLoader();
+
+ Properties taskDefs = new Properties();
+ if (customTaskDefs != null) {
+ InputStream taskDefsStream =
classLoader.getResourceAsStream(customTaskDefs);
+ try {
+ taskDefs.load(taskDefsStream);
+ } finally {
+ taskDefsStream.close();
+ }
+ }
+
+ BundleAntProject project = new BundleAntProject();
+ project.setCoreLoader(classLoader);
+ project.init();
+ project.setBaseDir(buildFile.getParentFile());
+
+ if (properties != null) {
+ for (Map.Entry<Object, Object> property : properties.entrySet()) {
+ project.setProperty(property.getKey().toString(),
property.getValue().toString());
+ }
+ }
+
+ // notice we are adding the listener after we set the properties - we do not
want the
+ // the properties echoed out in the log (in case they contain sensitive
passwords)
+ project.addBuildListener(new LoggerAntBuildListener(target, logFileOutput,
Project.MSG_DEBUG));
+ if (logStdOut) {
+ PrintWriter stdout = new PrintWriter(System.out);
+ project.addBuildListener(new LoggerAntBuildListener(target, stdout,
Project.MSG_INFO));
+ }
+
+ for (Map.Entry<Object, Object> taskDef : taskDefs.entrySet()) {
+ project.addTaskDefinition(taskDef.getKey().toString(),
Class.forName(taskDef.getValue().toString(),
+ true, classLoader));
+ }
+
+ ProjectHelper2 helper = new ProjectHelper2();
+ helper.parse(project, buildFile);
+
+ parseBundleFiles(project);
+ parseBundleConfiguration(project);
+
+ if (execute) {
+ project.executeTarget((target == null) ? project.getDefaultTarget() :
target);
+ }
+
+ return project;
+
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot run ANT on script [" + buildFile
+ "]. Cause: " + e, e);
+ } finally {
+ if (logFileOutput != null) {
+ logFileOutput.close();
+ }
+ }
+ }
+
+ private void parseBundleFiles(BundleAntProject project) {
+ Map<String, ? extends Task> refs = project.getReferences();
+ for (Map.Entry<String, ? extends Task> entry : refs.entrySet()) {
+ String refId = entry.getKey();
+ if (refId.startsWith("_bundlefile.")) {
+ Hashtable attribs =
entry.getValue().getRuntimeConfigurableWrapper().getAttributeMap();
+
+ if (!attribs.containsKey("name")) {
+ throw new BuildException("Property id=[" + refId + "]
must specify the 'name' attribute");
+ }
+ String name = attribs.get("name").toString();
+
+ // allow the bundle author to specify the bundle file in one of the
standard two ways
+ Object location = attribs.get("location");
+ Object value = attribs.get("value");
+
+ String bundleFilename;
+ if (location != null) {
+ bundleFilename = location.toString();
+ } else if (value != null) {
+ bundleFilename = value.toString();
+ } else {
+ throw new BuildException("Property id=[" + refId + "],
name=[" + name
+ + "] must specify the bundle file name in an attribute named
'location' or 'value'");
+ }
+
+ project.addBundleFile(name, bundleFilename);
+ }
+ }
+ }
+
+ private void parseBundleConfiguration(BundleAntProject project) {
+ Map<String, ? extends Task> refs = project.getReferences();
+ for (Map.Entry<String, ? extends Task> entry : refs.entrySet()) {
+ String refId = entry.getKey();
+ if (refId.startsWith("_bundleconfig.")) {
+ Hashtable attribs =
entry.getValue().getRuntimeConfigurableWrapper().getAttributeMap();
+
+ if (!attribs.containsKey("name")) {
+ throw new BuildException("Property id=[" + refId + "]
must specify the 'name' attribute");
+ }
+ String name = attribs.get("name").toString();
+
+ // allow the bundle author to specify the bundle config prop in one of
the standard two ways
+ Object location = attribs.get("location");
+ Object value = attribs.get("value");
+
+ String bundlePropValue;
+ if (location != null) {
+ bundlePropValue = location.toString();
+ } else if (value != null) {
+ bundlePropValue = value.toString();
+ } else {
+ throw new BuildException("Property id=[" + refId + "],
name=[" + name
+ + "] must specify the bundle configuration name in an
attribute named 'location' or 'value'");
+ }
+
+ PropertyDefinitionSimple prop = new PropertyDefinitionSimple(name,
"Needed by bundle recipe.", false,
+ PropertySimpleType.STRING);
+ prop.setDisplayName(name);
+ prop.setDefaultValue(bundlePropValue);// TODO: I would like to set
this-setDefaultValue is deprecated, how to do this?
+ ConfigurationDefinition configDef =
project.getConfigurationDefinition();
+ configDef.put(prop);
+ }
+ }
+ }
+}
diff --git
a/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleAntProject.java
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleAntProject.java
new file mode 100644
index 0000000..0dd282c
--- /dev/null
+++ b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleAntProject.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tools.ant.Project;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+
+public class BundleAntProject extends Project {
+ private final Map<String, String> bundleFiles = new HashMap<String,
String>();
+ private ConfigurationDefinition configDef;
+
+ public Map<String, String> getBundleFiles() {
+ return bundleFiles;
+ }
+
+ public void addBundleFile(String name, String filename) {
+ bundleFiles.put(name, filename);
+ }
+
+ public ConfigurationDefinition getConfigurationDefinition() {
+ if (configDef == null) {
+ configDef = new ConfigurationDefinition("antbundle", null);
+ }
+ return configDef;
+ }
+}
diff --git a/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleTask.java
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleTask.java
new file mode 100644
index 0000000..a21ca6e
--- /dev/null
+++ b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/BundleTask.java
@@ -0,0 +1,29 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.bundle.ant;
+
+import org.apache.tools.ant.BuildException;
+
+public class BundleTask extends AbstractBundleTask {
+ @Override
+ public void execute() throws BuildException {
+ // TODO this is a stub for a custom bundle task, in case we need one
+ return;
+ }
+}
\ No newline at end of file
diff --git
a/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/LoggerAntBuildListener.java
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/LoggerAntBuildListener.java
new file mode 100644
index 0000000..e7365e3
--- /dev/null
+++
b/modules/common/ant-bundle/src/main/java/org/rhq/bundle/ant/LoggerAntBuildListener.java
@@ -0,0 +1,115 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.bundle.ant;
+
+import java.io.PrintWriter;
+import java.util.Date;
+
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.Task;
+
+/**
+ * Listens for ANT build events and logs them to a log stream.
+ *
+ * @author John Mazzitelli
+ */
+public class LoggerAntBuildListener implements BuildListener {
+ private final String mainTarget;
+ private final PrintWriter output;
+ private final int priorityThreshold;
+
+ public LoggerAntBuildListener(String target, PrintWriter logFile, int
priorityThreshold) {
+ this.mainTarget = (target != null) ? target : "(default)";
+ this.output = logFile;
+ this.priorityThreshold = priorityThreshold;
+
+ // start with the date this was started
+ this.output.println("======================================");
+ this.output.println("ANT target [" + this.mainTarget + "]");
+ this.output.println(new Date().toString());
+ this.output.println("======================================");
+ }
+
+ public void buildFinished(BuildEvent event) {
+ logEvent(event, "FINISHED! [" + this.mainTarget + ']');
+ }
+
+ public void buildStarted(BuildEvent event) {
+ logEvent(event, "STARTED! [" + this.mainTarget + ']');
+ }
+
+ public void messageLogged(BuildEvent event) {
+ logEvent(event, null);
+ }
+
+ public void targetFinished(BuildEvent event) {
+ logEvent(event, null);
+ }
+
+ public void targetStarted(BuildEvent event) {
+ logEvent(event, null);
+ }
+
+ public void taskFinished(BuildEvent event) {
+ logEvent(event, null);
+ }
+
+ public void taskStarted(BuildEvent event) {
+ logEvent(event, null);
+ }
+
+ private void logEvent(BuildEvent event, String additionalMessage) {
+ if (event.getPriority() > this.priorityThreshold) {
+ return;
+ }
+
+ String message = event.getMessage();
+ Throwable exception = event.getException();
+ Target target = event.getTarget();
+ Task task = event.getTask();
+
+ if (additionalMessage != null) {
+ output.println(additionalMessage);
+ }
+
+ if (target != null) {
+ output.print("[" + target.getName() + "] ");
+ }
+
+ if (task != null) {
+ output.print("[" + task.getTaskName() + "] ");
+ }
+
+ if (message != null) {
+ output.print(message);
+ }
+
+ if (exception != null) {
+ output.println();
+ exception.printStackTrace(output);
+ }
+
+ output.println();
+ output.flush();
+
+ return;
+ }
+}
\ No newline at end of file
diff --git a/modules/common/ant-bundle/src/main/resources/bundle-ant-tasks.properties
b/modules/common/ant-bundle/src/main/resources/bundle-ant-tasks.properties
new file mode 100644
index 0000000..6f84e21
--- /dev/null
+++ b/modules/common/ant-bundle/src/main/resources/bundle-ant-tasks.properties
@@ -0,0 +1 @@
+bundle-task=org.rhq.bundle.ant.BundleTask
\ No newline at end of file
diff --git
a/modules/common/ant-bundle/src/test/java/org/rhq/bundle/ant/AntLauncherTest.java
b/modules/common/ant-bundle/src/test/java/org/rhq/bundle/ant/AntLauncherTest.java
new file mode 100644
index 0000000..01de89e
--- /dev/null
+++ b/modules/common/ant-bundle/src/test/java/org/rhq/bundle/ant/AntLauncherTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.ant;
+
+import java.io.File;
+import java.util.Map;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+
+@Test
+public class AntLauncherTest {
+ private File logFile;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ logFile = new File("target/test-ant-log.txt");
+ if (logFile.exists()) {
+ if (!logFile.delete()) {
+ System.out.println("Failed to clean up test - log file did not
delete");
+ }
+ }
+ return;
+ }
+
+ public void testSimpleParseTest() throws Exception {
+ AntLauncher ant = new AntLauncher();
+ BundleAntProject project =
ant.startAnt(getBuildXml("simple-build.xml"), "unnecessary-target",
null, null,
+ logFile, true, false);
+ assert project != null;
+ Map<String, String> bundleFiles = project.getBundleFiles();
+ assert bundleFiles != null;
+ assert bundleFiles.size() == 2 : bundleFiles;
+ assert bundleFiles.get("f").equals("file.txt") :
bundleFiles;
+ assert bundleFiles.get("pkg").equals("package.zip") :
bundleFiles;
+
+ ConfigurationDefinition configDef = project.getConfigurationDefinition();
+ assert configDef.getPropertyDefinitions().size() == 2;
+ assert configDef.getPropertyDefinitionSimple("custom.prop1") != null;
+ assert configDef.getPropertyDefinitionSimple("custom.prop2") != null;
+ }
+
+ public void testSimpleExecTest() throws Exception {
+ AntLauncher ant = new AntLauncher();
+ BundleAntProject project =
ant.startAnt(getBuildXml("simple-build.xml"), "first-target", null,
null, logFile,
+ true, true);
+ Map<String, String> bundleFiles = project.getBundleFiles();
+ assert bundleFiles != null;
+ assert bundleFiles.size() == 2 : bundleFiles;
+ assert bundleFiles.get("f").equals("file.txt") :
bundleFiles;
+ assert bundleFiles.get("pkg").equals("package.zip") :
bundleFiles;
+
+ ConfigurationDefinition configDef = project.getConfigurationDefinition();
+ assert configDef.getPropertyDefinitions().size() == 2;
+ assert configDef.getPropertyDefinitionSimple("custom.prop1") != null;
+ assert configDef.getPropertyDefinitionSimple("custom.prop2") != null;
+ }
+
+ private File getBuildXml(String name) throws Exception {
+ File file = new File("target/test-classes", name);
+ assert file.exists() : "the test ant build script doesn't exist: "
+ file.getAbsolutePath();
+ return file;
+ }
+}
diff --git a/modules/common/ant-bundle/src/test/resources/simple-build.xml
b/modules/common/ant-bundle/src/test/resources/simple-build.xml
new file mode 100644
index 0000000..fecb376
--- /dev/null
+++ b/modules/common/ant-bundle/src/test/resources/simple-build.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<project name="simple-bundle-test">
+ <property id="_bundlefile.1" name="f"
location="file.txt" />
+ <property id="_bundleconfig.1" name="custom.prop1"
location="1" />
+
+ <target name="first-target">
+ <echo>Hello!!!!!!!!</echo>
+ <property id="_bundlefile.2" name="pkg"
value="package.zip" />
+ <property id="_bundleconfig.2" name="custom.prop2"
value="2" />
+ <echo>World!!!!!!!!</echo>
+ </target>
+</project>
\ No newline at end of file
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 8abfe11..1e561b4 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -67,5 +67,6 @@
<modules>
<module>jboss-as</module>
<module>filetemplate-bundle</module>
+ <module>ant-bundle</module>
</modules>
</project>
\ No newline at end of file
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index 07c49a8..0e83859 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -143,12 +143,12 @@ public class ServerPluginService implements
ServerPluginServiceManagement {
File tmpDir = LookupUtil.getCoreServer().getJBossServerTempDir();
- // TODO: determine what things to hide from our war classloader
- //StringBuilder defaultRegex = new StringBuilder();
- //defaultRegex.append("(package\\.with\\.classes\\.to\\.hide\\..*)|");
+ // determine what things to hide from our war classloader
+ StringBuilder defaultRegex = new StringBuilder();
+ defaultRegex.append("(org\\.apache\\.tools\\..*)"); // ant.jar
MasterServerPluginContainerConfiguration config;
- config = new MasterServerPluginContainerConfiguration(pluginDir, dataDir, tmpDir,
null);
+ config = new MasterServerPluginContainerConfiguration(pluginDir, dataDir, tmpDir,
defaultRegex.toString());
pc.initialize(config);
return pc;
}
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml
b/modules/enterprise/server/plugins/ant-bundle/pom.xml
new file mode 100644
index 0000000..b044ca3
--- /dev/null
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -0,0 +1,214 @@
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server-plugins-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-serverplugin-ant-bundle</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Ant Bundle Server Plugin</name>
+ <description>Server side plugin that manages ant-scripted
bundles</description>
+
+ <scm>
+
<
connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/ente...
+
<
developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/mod...
+ </scm>
+
+ <properties>
+
<scm.module.path>modules/enterprise/server/plugins/ant-bundle/</scm.module.path>
+ </properties>
+
+ <dependencies>
+
+ <!-- Internal Deps -->
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-client-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-ant-bundle-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- 3rd Party Deps -->
+
+ <!-- TODO: This is a fix for the Javac bug requiring annotations to be
+ available when compiling dependent classes. It is fixed in JDK 6 -->
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss.jboss-embeddable-ejb3</groupId>
+ <artifactId>hibernate-all</artifactId>
+ <version>1.0.0.Alpha9</version>
+ <scope>provided</scope>
+ <!-- needed for referenced domain entities that use Hibernate annotations
-->
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <!--
+ <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.0</version>
+ <executions>
+ <execution>
+ <id>copy-rhq-plugins</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+
<artifactId>rhq-ant-bundle-common</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.6.5</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ <version>1.6.5</version>
+ </artifactItem>
+
+ <!-- include some optional ant tasks for users to be
able to use -->
+ <artifactItem>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>1.0b3</version>
+ </artifactItem>
+
+ </artifactItems>
+
<outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../../../..</rhq.rootDir>
+
<rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+
<rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-serverplugins</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}"
/>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
${deployment.file}...</echo>
+ <jar destfile="${deployment.file}"
basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
${deployment.file}...</echo>
+ <delete file="${deployment.file}"
/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating META-INF dir in
${deployment.file}...</echo>
+ <unjar
src="${project.build.directory}/${project.build.finalName}.jar"
dest="${project.build.outputDirectory}">
+ <patternset>
+ <include name="META-INF/**"
/>
+ </patternset>
+ </unjar>
+ <jar destfile="${deployment.file}"
manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
+ update="true">
+ </jar>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
\ No newline at end of file
diff --git
a/modules/enterprise/server/plugins/ant-bundle/src/main/java/org/rhq/enterprise/server/plugins/ant/AntBundleServerPluginComponent.java
b/modules/enterprise/server/plugins/ant-bundle/src/main/java/org/rhq/enterprise/server/plugins/ant/AntBundleServerPluginComponent.java
new file mode 100644
index 0000000..15e4ecb
--- /dev/null
+++
b/modules/enterprise/server/plugins/ant-bundle/src/main/java/org/rhq/enterprise/server/plugins/ant/AntBundleServerPluginComponent.java
@@ -0,0 +1,125 @@
+/*
+ * 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.plugins.ant;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bundle.ant.AntLauncher;
+import org.rhq.bundle.ant.BundleAntProject;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.bundle.RecipeParseResults;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginFacet;
+
+/**
+ * A bundle server-side plugin component that the server uses to process ant-based
bundles.
+ *
+ * @author John Mazzitelli
+ */
+public class AntBundleServerPluginComponent implements ServerPluginComponent,
BundleServerPluginFacet {
+
+ private final Log log = LogFactory.getLog(AntBundleServerPluginComponent.class);
+
+ private ServerPluginContext context;
+ private File tmpDirectory;
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ this.context = context;
+ this.tmpDirectory = new File(this.context.getTemporaryDirectory(),
"ant-bundle-server-plugin");
+ this.tmpDirectory.mkdirs();
+ if (!this.tmpDirectory.exists() || !this.tmpDirectory.isDirectory()) {
+ throw new Exception("Failed to create tmp dir [" +
this.tmpDirectory + "] - cannot process ant bundles");
+ }
+ log.debug("The ant bundle plugin has been initialized: " + this);
+ }
+
+ public void start() {
+ log.debug("The ant bundle plugin has started: " + this);
+ }
+
+ public void stop() {
+ log.debug("The ant bundle plugin has stopped: " + this);
+ }
+
+ public void shutdown() {
+ log.debug("The ant bundle plugin has been shut down: " + this);
+ }
+
+ public RecipeParseResults parseRecipe(String recipe) throws Exception {
+
+ Map<String, String> bundleFiles = null;
+ ConfigurationDefinition configDef = null;
+ RecipeParseResults results;
+
+ File recipeFile = File.createTempFile("ant-bundle-recipe",
".xml", this.tmpDirectory);
+ File logFile = File.createTempFile("ant-bundle-recipe",
".log", this.tmpDirectory);
+ try {
+ // store the recipe in the tmp recipe file
+ ByteArrayInputStream in = new ByteArrayInputStream(recipe.getBytes());
+ FileOutputStream out = new FileOutputStream(recipeFile);
+ StreamUtil.copy(in, out);
+
+ // parse, but do not execute, the ant script
+ AntLauncher antLauncher = new AntLauncher();
+ BundleAntProject project = antLauncher.startAnt(recipeFile, null, null, null,
logFile, false, false);
+
+ // obtain the parse results
+ bundleFiles = project.getBundleFiles();
+ configDef = project.getConfigurationDefinition();
+ } catch (Throwable t) {
+ if (log.isDebugEnabled()) {
+ try {
+ log.debug(new String(StreamUtil.slurp(new
FileInputStream(logFile))));
+ } catch (Exception e) {
+ }
+ }
+ throw new Exception("Failed to parse the bundle ANT script", t);
+ } finally {
+ recipeFile.delete();
+ logFile.delete();
+ }
+
+ results = new RecipeParseResults(configDef, new
HashSet<String>(bundleFiles.values()));
+ return results;
+
+ }
+
+ @Override
+ public String toString() {
+ if (this.context == null) {
+ return "<no context>";
+ }
+
+ StringBuilder str = new StringBuilder();
+
str.append("plugin-key=").append(this.context.getPluginEnvironment().getPluginKey()).append(",");
+
str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl());
+ return str.toString();
+ }
+}
diff --git
a/modules/enterprise/server/plugins/ant-bundle/src/main/resources/META-INF/rhq-serverplugin.xml
b/modules/enterprise/server/plugins/ant-bundle/src/main/resources/META-INF/rhq-serverplugin.xml
new file mode 100644
index 0000000..23208b7
--- /dev/null
+++
b/modules/enterprise/server/plugins/ant-bundle/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<bundle-plugin name="AntBundleServerPlugin"
+ displayName="Ant Bundle Processor"
+ description="Processes bundles whose recipes are Ant scripts"
+ package="org.rhq.enterprise.server.plugins.ant"
+ xmlns="urn:xmlns:rhq-serverplugin.bundle"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <serverplugin:help><![CDATA[
+ Processes Ant bundles on the server side.
+ ]]></serverplugin:help>
+
+ <serverplugin:plugin-component
class="AntBundleServerPluginComponent">
+ </serverplugin:plugin-component>
+
+ <bundle type="Ant Bundle"/>
+
+</bundle-plugin>
diff --git a/modules/enterprise/server/plugins/pom.xml
b/modules/enterprise/server/plugins/pom.xml
index b86cde2..06f91cf 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -84,6 +84,7 @@
<module>alert-subject</module>
<module>cobbler</module>
<module>filetemplate-bundle</module>
+ <module>ant-bundle</module>
<module>validate-all-serverplugins</module>
</modules>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 58e3d40..9c7cc74 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -54,6 +54,7 @@
<pathelement
location="../alert-subject/target/alert-subject-${project.version}.jar" />
<pathelement
location="../cobbler/target/cobbler-${project.version}.jar" />
<pathelement
location="../filetemplate-bundle/target/rhq-serverplugin-filetemplate-bundle-${project.version}.jar"
/>
+ <pathelement
location="../ant-bundle/target/rhq-serverplugin-ant-bundle-${project.version}.jar"
/>
<pathelement
location="../perspectives/core/target/rhq-core-perspective-${project.version}.jar"
/>
</classpath>
<sysproperty key="org.apache.commons.logging.Log"
value="org.apache.commons.logging.impl.SimpleLog" />
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
new file mode 100644
index 0000000..3777af9
--- /dev/null
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -0,0 +1,267 @@
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-plugins-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-ant-bundle-plugin</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Ant Bundle Plugin</name>
+ <description>a plugin that processes ant-based bundles</description>
+
+ <scm>
+
<
connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plug...
+
<
developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/mod...
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/plugins/ant-bundle/</scm.module.path>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-ant-bundle-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.0</version>
+ <executions>
+ <execution>
+ <id>copy-rhq-plugins</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+
<artifactId>rhq-ant-bundle-common</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.6.5</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ <version>1.6.5</version>
+ </artifactItem>
+
+ <!-- include some optional ant tasks for users to be
able to use -->
+ <artifactItem>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>1.0b3</version>
+ </artifactItem>
+
+ </artifactItems>
+
<outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>integration-tests</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <build>
+ <plugins>
+ <!-- Integration testing voodoo to load and test this plugin with
its plugin dependencies -->
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <echo>Setting up plugin dependencies for
${project.artifactId}-${project.version}.jar...</echo>
+ <property
name="settings.localRepository" location="${user.home}/.m2/repository"
/>
+ <mkdir dir="target/itest" />
+ <mkdir dir="target/itest/plugins"
/>
+ <mkdir dir="target/itest/lib" />
+ <copy toDir="target/itest/plugins"
flatten="true">
+ <fileset
dir="${settings.localRepository}/">
+ <include
name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar"
/>
+ </fileset>
+ <fileset
dir="${project.build.directory}">
+ <include
name="${project.artifactId}-${project.version}.jar" />
+ </fileset>
+ </copy>
+ <unzip dest="target/itest/lib">
+ <fileset
dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}"
includes="*.zip" />
+ <patternset>
+ <include
name="**/lib/sigar.jar" />
+ <include
name="**/lib/bcel*.jar" />
+ <include name="**/lib/*.so"
/>
+ <include name="**/lib/*.sl"
/>
+ <include name="**/lib/*.dll"
/>
+ <include
name="**/lib/*.dylib" />
+ </patternset>
+ </unzip>
+ <move todir="target/itest/lib"
flatten="true">
+ <fileset
dir="target/itest/lib">
+ <include name="**/lib/*"
/>
+ </fileset>
+ </move>
+ <delete
dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>surefire-it</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${maven.test.skip}</skip>
+
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+
<useSystemClassLoader>false</useSystemClassLoader>
+
<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--
+
<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent
-Djava.compiler=NONE
+
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
+ <systemProperties>
+ <property>
+ <name>project.artifactId</name>
+
<value>${project.artifactId}</value>
+ </property>
+ <property>
+ <name>project.version</name>
+
<value>${project.version}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+
+ </build>
+ </profile>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+
<rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+
<rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}"
/>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
${deployment.file}...</echo>
+ <jar destfile="${deployment.file}"
basedir="${project.build.outputDirectory}" update="true" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating META-INF dir in
${deployment.file}...</echo>
+ <unjar
src="${project.build.directory}/${project.build.finalName}.jar"
dest="${project.build.outputDirectory}">
+ <patternset>
+ <include name="META-INF/**"
/>
+ </patternset>
+ </unjar>
+ <jar destfile="${deployment.file}"
manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
+ update="true">
+ </jar>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file"
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
${deployment.file}...</echo>
+ <delete file="${deployment.file}"
/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git
a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
new file mode 100644
index 0000000..f523be1
--- /dev/null
+++
b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
@@ -0,0 +1,136 @@
+/*
+ * 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.plugins.ant;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bundle.ant.AntLauncher;
+import org.rhq.bundle.ant.BundleAntProject;
+import org.rhq.core.domain.bundle.BundleDeployDefinition;
+import org.rhq.core.domain.bundle.BundleVersion;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
+import org.rhq.core.pluginapi.bundle.BundleDeployResult;
+import org.rhq.core.pluginapi.bundle.BundleFacet;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * @author John Mazzitelli
+ */
+@SuppressWarnings("unchecked")
+public class AntBundlePluginComponent implements ResourceComponent, BundleFacet {
+
+ private final Log log = LogFactory.getLog(AntBundlePluginComponent.class);
+
+ private ResourceContext resourceContext;
+
+ private File tmpDirectory;
+
+ public void start(ResourceContext context) throws Exception {
+ resourceContext = context;
+ this.tmpDirectory = new File(context.getTemporaryDirectory(),
"ant-bundle-plugin");
+ this.tmpDirectory.mkdirs();
+ if (!this.tmpDirectory.exists() || !this.tmpDirectory.isDirectory()) {
+ throw new Exception("Failed to create tmp dir [" +
this.tmpDirectory + "] - cannot process ant bundles");
+ }
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+
+ public BundleDeployResult deployBundle(BundleDeployRequest request) {
+ BundleDeployResult result = new BundleDeployResult();
+ try {
+ BundleDeployDefinition bundleDeployDef =
request.getBundleDeployDefinition();
+ BundleVersion bundleVersion = bundleDeployDef.getBundleVersion();
+
+ String recipe = bundleVersion.getRecipe();
+ File recipeFile = File.createTempFile("ant-bundle-recipe",
".xml", request.getBundleFilesLocation());
+ File logFile = File.createTempFile("ant-bundle-recipe",
".log", this.tmpDirectory);
+ try {
+ // store the recipe in the tmp recipe file
+ ByteArrayInputStream in = new ByteArrayInputStream(recipe.getBytes());
+ FileOutputStream out = new FileOutputStream(recipeFile);
+ StreamUtil.copy(in, out);
+
+ // get the bundle's configuration values and the global system facts
and
+ // add them as ant properties so the ant script can get their values
+ Configuration config = bundleDeployDef.getConfiguration();
+ Map<String, String> sysFacts =
SystemInfoFactory.fetchTemplateEngine().getTokens();
+ Properties antProps = new Properties();
+ for (Map.Entry<String, String> fact : sysFacts.entrySet()) {
+ antProps.setProperty(fact.getKey(), fact.getValue());
+ }
+ if (config != null) {
+ Map<String, Property> allProperties =
config.getAllProperties();
+ for (Map.Entry<String, Property> entry :
allProperties.entrySet()) {
+ String name = entry.getKey();
+ Property prop = entry.getValue();
+ String value;
+ if (prop instanceof PropertySimple) {
+ value = ((PropertySimple) prop).getStringValue();
+ } else {
+ // for now, just skip all property lists and maps, just
assume we are getting simples
+ continue;
+ }
+ antProps.setProperty(name, value);
+ }
+ }
+
+ // parse & execute, the ant script
+ AntLauncher antLauncher = new AntLauncher();
+ BundleAntProject project = antLauncher.startAnt(recipeFile, null, null,
antProps, logFile, false, true);
+ } catch (Throwable t) {
+ if (log.isDebugEnabled()) {
+ try {
+ log.debug(new String(StreamUtil.slurp(new
FileInputStream(logFile))));
+ } catch (Exception e) {
+ }
+ }
+ throw new Exception("Failed to parse the bundle ANT script",
t);
+ } finally {
+ recipeFile.delete();
+ logFile.delete();
+ }
+
+ } catch (Throwable t) {
+ log.error("Failed to deploy bundle [" + request + "]",
t);
+ result.setErrorMessage(t);
+ }
+ return result;
+ }
+}
diff --git
a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginDiscoveryComponent.java
b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginDiscoveryComponent.java
new file mode 100644
index 0000000..50a2f86
--- /dev/null
+++
b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginDiscoveryComponent.java
@@ -0,0 +1,51 @@
+/*
+ * 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 as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.plugins.ant;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+/**
+ * @author John Mazzitelli
+ */
+@SuppressWarnings("unchecked")
+public class AntBundlePluginDiscoveryComponent implements ResourceDiscoveryComponent {
+ //private final Log log =
LogFactory.getLog(FileTemplateBundlePluginDiscoveryComponent.class);
+
+ public Set<DiscoveredResourceDetails>
discoverResources(ResourceDiscoveryContext context) {
+
+ HashSet<DiscoveredResourceDetails> set = new
HashSet<DiscoveredResourceDetails>();
+
+ String key = "ant-bundle";
+ String name = "Ant Bundle Handler";
+ String version = this.getClass().getPackage().getImplementationVersion();
+ String description = "Processes bundles whose recipes are Ant
scripts";
+
+ DiscoveredResourceDetails resource = new
DiscoveredResourceDetails(context.getResourceType(), key, name,
+ version, description, null, null);
+
+ set.add(resource);
+
+ return set;
+ }
+}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/main/resources/META-INF/rhq-plugin.xml
b/modules/plugins/ant-bundle/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..ce2b150
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="AntBundlePlugin"
+ displayName="Ant Bundle Plugin"
+ package="org.rhq.plugins.ant"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+
+ <server name="Ant Bundle Handler Server"
+ discovery="AntBundlePluginDiscoveryComponent"
+ class="AntBundlePluginComponent"
+ singleton="true"
+ description="This plugin is used to process Ant bundles">
+
+ <bundle type="Ant Bundle" />
+
+ </server>
+</plugin>
diff --git
a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
new file mode 100644
index 0000000..4f2f28b
--- /dev/null
+++
b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.ant;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.bundle.Bundle;
+import org.rhq.core.domain.bundle.BundleDeployDefinition;
+import org.rhq.core.domain.bundle.BundleType;
+import org.rhq.core.domain.bundle.BundleVersion;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
+import org.rhq.core.pluginapi.bundle.BundleDeployResult;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.stream.StreamUtil;
+
+@Test
+public class AntBundlePluginComponentTest {
+
+ private AntBundlePluginComponent plugin;
+ private File tmpDir;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ tmpDir = new File("target/antbundletest");
+ tmpDir.mkdirs();
+ plugin = new AntBundlePluginComponent();
+ ResourceType type = new ResourceType("antBundleTestType",
"antBundleTestPlugin", ResourceCategory.SERVER, null);
+ Resource resource = new Resource("antBundleTestKey",
"antBundleTestName", type);
+ ResourceContext<?> context = new ResourceContext(resource, null, null,
+ SystemInfoFactory.createJavaSystemInfo(), tmpDir, null,
"antBundleTestPC", null, null, null, null, null);
+ plugin.start(context);
+ }
+
+ @BeforeClass
+ @AfterMethod
+ public void cleanTmpDir() {
+ if (tmpDir != null) {
+ File[] files = tmpDir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ file.delete();
+ }
+ }
+ }
+ }
+
+ public void testSimpleBundle() throws Exception {
+ ResourceType resourceType = new ResourceType("testSimpleBundle",
"plugin", ResourceCategory.SERVER, null);
+ BundleType bundleType = new BundleType("testSimpleBundle",
resourceType);
+ Bundle bundle = new Bundle("testSimpleBundle", bundleType);
+ BundleVersion bundleVersion = new BundleVersion("testSimpleBundle",
"1.0", bundle,
+ getRecipeFromFile("simple-build.xml"));
+
+ BundleDeployDefinition deployDef = new BundleDeployDefinition();
+ deployDef.setBundleVersion(bundleVersion);
+ deployDef.setConfiguration(null);
+
+ BundleDeployRequest request = new BundleDeployRequest();
+ request.setBundleFilesLocation(tmpDir);
+ request.setBundleDeployDefinition(deployDef);
+
+ BundleDeployResult results = plugin.deployBundle(request);
+
+ assertResultsSuccess(results);
+
+ // our ant script wrote some output that we should verify to make sure we ran it
+ File outputFile = new File(tmpDir, "output.1");
+ String output = new String(StreamUtil.slurp(new FileInputStream(outputFile)));
+ assert output.equals("HELLO WORLD") : output;
+
+ }
+
+ public void testAntBundle() throws Exception {
+ ResourceType resourceType = new ResourceType("testSimpleBundle",
"plugin", ResourceCategory.SERVER, null);
+ BundleType bundleType = new BundleType("testSimpleBundle",
resourceType);
+ Bundle bundle = new Bundle("testSimpleBundle", bundleType);
+ BundleVersion bundleVersion = new BundleVersion("testSimpleBundle",
"1.0", bundle,
+ getRecipeFromFile("test-build.xml"));
+
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("custom.prop1", "custom property
1"));
+ config.put(new PropertySimple("custom.prop2", "custom property
2"));
+
+ BundleDeployDefinition deployDef = new BundleDeployDefinition();
+ deployDef.setBundleVersion(bundleVersion);
+ deployDef.setConfiguration(config);
+
+ File file1 = new File(tmpDir, "file.txt");
+ File file2 = new File(tmpDir, "package.zip");
+ assert file1.createNewFile() : "could not create our mock bundle
file";
+ assert file2.createNewFile() : "could not create our mock bundle
file";
+
+ BundleDeployRequest request = new BundleDeployRequest();
+ request.setBundleFilesLocation(tmpDir);
+ request.setBundleDeployDefinition(deployDef);
+
+ BundleDeployResult results = plugin.deployBundle(request);
+
+ assertResultsSuccess(results);
+
+ // our ant script wrote some output that we should verify to make sure we ran it
+ File outputFile = new File(tmpDir, "output.2");
+ Properties props = new Properties();
+ props.load(new FileInputStream(outputFile));
+ assert props.getProperty("prop1").equals("custom property 1")
: props;
+ assert props.getProperty("prop2").equals("custom property 2")
: props;
+ assert props.getProperty("f.exists").equals("true") : props;
+ assert props.getProperty("pkg.exists").equals("true") :
props;
+ assert
props.getProperty("hostname").equals(SystemInfoFactory.createSystemInfo().getHostname())
: props;
+ assert
props.getProperty("tmpdir").equals(System.getProperty("java.io.tmpdir"))
: props;
+ }
+
+ private void assertResultsSuccess(BundleDeployResult results) {
+ if (results.getErrorMessage() != null) {
+ assert false : "Failed to process bundle: [" +
results.getErrorMessage() + "]";
+ }
+ }
+
+ private String getRecipeFromFile(String filename) {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream(filename);
+ byte[] contents = StreamUtil.slurp(stream);
+ return new String(contents);
+ }
+}
diff --git a/modules/plugins/ant-bundle/src/test/resources/log4j.xml
b/modules/plugins/ant-bundle/src/test/resources/log4j.xml
new file mode 100644
index 0000000..181834e
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/test/resources/log4j.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- tests configuration that only dumps WARN or higher messages due to appender
threadhold -->
+
+<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
+
+ <appender name="CONSOLE"
class="org.apache.log4j.ConsoleAppender">
+ <param name="Threshold" value="ERROR"/>
+ <param name="Target" value="System.out"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%t]
(%c{5}) - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE"
class="org.apache.log4j.FileAppender">
+ <param name="File" value="target/test.log"/>
+ <param name="Threshold" value="DEBUG"/>
+ <param name="Append" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM
HH:mm:ss,SSS} (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <category name="org.rhq">
+ <priority value="DEBUG"/>
+ </category>
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
diff --git a/modules/plugins/ant-bundle/src/test/resources/simple-build.xml
b/modules/plugins/ant-bundle/src/test/resources/simple-build.xml
new file mode 100644
index 0000000..c1606dc
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/test/resources/simple-build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<project name="test" default="init">
+ <property name="outfile" value="${basedir}/output.1" />
+
+ <target name="init">
+ <echo file="${outfile}" message="HELLO WORLD"/>
+ </target>
+</project>
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/resources/test-build.xml
b/modules/plugins/ant-bundle/src/test/resources/test-build.xml
new file mode 100644
index 0000000..4b0b778
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/test/resources/test-build.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<project name="simple-build" default="first-target">
+ <property id="_bundlefile.1" name="f"
location="file.txt" />
+ <property id="_bundleconfig.1" name="custom.prop1"
location="1" />
+
+ <property name="outfile" value="${basedir}/output.2" />
+
+ <target name="first-target">
+ <property id="_bundlefile.2" name="pkg"
value="${basedir}/package.zip" />
+ <property id="_bundleconfig.2" name="custom.prop2"
value="2" />
+
+ <condition property="file.f.exists">
+ <available file="${f}" />
+ </condition>
+ <condition property="file.pkg.exists">
+ <available file="${pkg}" />
+ </condition>
+
+ <echo file="${outfile}">prop1=${custom.prop1}
+prop2=${custom.prop2}
+f.exists=${file.f.exists}
+pkg.exists=${file.pkg.exists}
+hostname=${rhq.system.hostname}
+tmpdir=${rhq.system.sysprop.java.io.tmpdir}
+ </echo>
+ </target>
+</project>
\ No newline at end of file
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index d41b7b1..76ee0ee 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -162,6 +162,7 @@
<!-- bundle plugins -->
<module>filetemplate-bundle</module>
+ <module>ant-bundle</module>
</modules>
</profile>
diff --git a/modules/plugins/validate-all-plugins/pom.xml
b/modules/plugins/validate-all-plugins/pom.xml
index 01e2a34..b3d5e87 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -62,6 +62,7 @@
<pathelement
location="../virt/target/rhq-virt-plugin-${project.version}.jar" />
<pathelement
location="../kickstart/target/rhq-kickstart-plugin-${project.version}.jar"
/>
<pathelement
location="../filetemplate-bundle/target/rhq-filetemplate-bundle-plugin-${project.version}.jar"
/>
+ <pathelement
location="../ant-bundle/target/rhq-ant-bundle-plugin-${project.version}.jar"
/>
</classpath>
<sysproperty key="org.apache.commons.logging.Log"
value="org.apache.commons.logging.impl.SimpleLog" />
<!--
commit d4e2842142ab368dee94fdee322f8168837956aa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 29 00:29:04 2010 -0400
force the filetemplate plugin to use its own gnu getopt just to isolate it from the
servers's version (this probably isn't that important to do)
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index 4a3536e..44cdb03 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -101,6 +101,12 @@
<version>${project.version}</version>
</artifactItem>
+ <artifactItem>
+ <groupId>gnu-getopt</groupId>
+ <artifactId>getopt</artifactId>
+ <!-- NOTE: The version is defined in the root
POM's dependencyManagement section. -->
+ </artifactItem>
+
</artifactItems>
<outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
</configuration>
commit 5f33867f613ccc768ef2e30efb9ffc722d6b77fa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 29 00:27:49 2010 -0400
allow public API to obtain tokens from the template engine
diff --git a/modules/core/util/src/main/java/org/rhq/core/template/TemplateEngine.java
b/modules/core/util/src/main/java/org/rhq/core/template/TemplateEngine.java
index d748463..79ad1ff 100644
--- a/modules/core/util/src/main/java/org/rhq/core/template/TemplateEngine.java
+++ b/modules/core/util/src/main/java/org/rhq/core/template/TemplateEngine.java
@@ -37,6 +37,10 @@ public class TemplateEngine implements Serializable {
this.tokens = tokens;
}
+ public Map<String, String> getTokens() {
+ return this.tokens;
+ }
+
public String replaceTokens(String input) {
StringBuffer buffer = new StringBuffer();
Matcher matcher = tokenPattern.matcher(input);
commit 0c03d1eb6b3b03cabe58a17dbb98bd43307ca127
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 29 00:27:11 2010 -0400
make the parse call directly in the bundle PC so we can set context CL
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
index 7b41da0..61715df 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
@@ -79,7 +79,6 @@ import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.content.ContentManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.core.AgentManagerLocal;
-import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginFacet;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
import org.rhq.enterprise.server.util.HibernateDetachUtility;
@@ -248,12 +247,11 @@ public class BundleManagerBean implements BundleManagerLocal,
BundleManagerRemot
// parse the recipe (validation occurs here) and get the config def and list of
files
BundleType bundleType = bundle.getBundleType();
- BundleServerPluginFacet bp =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager()
- .getBundleServerPluginFacet(bundleType.getName());
RecipeParseResults results;
try {
- results = bp.parseRecipe(recipe);
+ results =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager().parseRecipe(
+ bundleType.getName(), recipe);
} catch (Exception e) {
// ensure that we throw a runtime exception to force a rollback
throw new RuntimeException("Failed to parse recipe", e);
@@ -574,9 +572,8 @@ public class BundleManagerBean implements BundleManagerLocal,
BundleManagerRemot
// parse the recipe (validation occurs here) and get the config def and list of
files
BundleType bundleType = bundleVersion.getBundle().getBundleType();
- BundleServerPluginFacet bp =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager()
- .getBundleServerPluginFacet(bundleType.getName());
- RecipeParseResults parseResults = bp.parseRecipe(bundleVersion.getRecipe());
+ RecipeParseResults parseResults =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager()
+ .parseRecipe(bundleType.getName(), bundleVersion.getRecipe());
Set<String> result = parseResults.getBundleFileNames();
@@ -613,9 +610,8 @@ public class BundleManagerBean implements BundleManagerLocal,
BundleManagerRemot
// parse the recipe (validation occurs here) and get the config def and list of
files
BundleType bundleType = bundleVersion.getBundle().getBundleType();
- BundleServerPluginFacet bp =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager()
- .getBundleServerPluginFacet(bundleType.getName());
- RecipeParseResults parseResults = bp.parseRecipe(bundleVersion.getRecipe());
+ RecipeParseResults parseResults =
BundleManagerHelper.getPluginContainer().getBundleServerPluginManager()
+ .parseRecipe(bundleType.getName(), bundleVersion.getRecipe());
Set<String> filenames = parseResults.getBundleFileNames();
Map<String, Boolean> result = new HashMap<String,
Boolean>(filenames.size());
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/bundle/BundleServerPluginManager.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/bundle/BundleServerPluginManager.java
index 68f8a0f..7387f3a 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/bundle/BundleServerPluginManager.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/bundle/BundleServerPluginManager.java
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.server.plugin.pc.bundle;
+import org.rhq.enterprise.server.bundle.RecipeParseResults;
import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
@@ -68,28 +69,51 @@ public class BundleServerPluginManager extends ServerPluginManager {
}
/**
- * Given the {@link BundleType#getName() name of a bundle type}, this will return the
stateful plugin component
- * that manages bundles of that type.
+ * Given the {@link BundleType#getName() name of a bundle type}, this will parse the
given recipe by asking the
+ * bundle plugin that can parse a recipe of that bundle type.
*
- * @param bundleTypeName
+ * @param bundleTypeName essentially identifies the kind of recipe that is to be
parsed
+ * @param recipe the recipe to parse
*
- * @return the plugin component object that will manage bundles of the named bundle
type; <code>null</code> if there is no plugin
- * that can support the given bundle type
+ * @return the results of the parse
+ *
+ * @throws Exception if the recipe could not be parsed successfully
*/
- public BundleServerPluginFacet getBundleServerPluginFacet(String bundleTypeName) {
+ public RecipeParseResults parseRecipe(String bundleTypeName, String recipe) throws
Exception {
+
if (bundleTypeName == null) {
throw new IllegalArgumentException("bundleTypeName == null");
}
+ if (recipe == null) {
+ throw new IllegalArgumentException("recipe == null");
+ }
+ // find the plugin environment for the bundle plugin of the given type
+ ServerPluginEnvironment pluginEnv = null;
for (ServerPluginEnvironment env : getPluginEnvironments()) {
BundlePluginDescriptorType descriptor = (BundlePluginDescriptorType)
env.getPluginDescriptor();
if (bundleTypeName.equals(descriptor.getBundle().getType())) {
- ServerPluginComponent component =
getServerPluginComponent(env.getPluginKey().getPluginName());
- // we know this cast will work because our loadPlugin ensured that this
component implements this interface
- return (BundleServerPluginFacet) component;
+ pluginEnv = env;
+ break;
}
}
- return null;
+ if (pluginEnv == null) {
+ throw new IllegalArgumentException("Bundle type [" + bundleTypeName
+ "] is not known to the system");
+ }
+
+ // get the facet and call the parse method in the appropriate classloader
+ String pluginName = pluginEnv.getPluginKey().getPluginName();
+ ServerPluginComponent component = getServerPluginComponent(pluginName);
+ BundleServerPluginFacet facet = (BundleServerPluginFacet) component; // we know
this cast will work because our loadPlugin ensured so
+ getLog().debug("Bundle server plugin [" + pluginName + "] is
parsing a bundle recipe");
+ ClassLoader originalContextClassLoader =
Thread.currentThread().getContextClassLoader();
+ try {
+
Thread.currentThread().setContextClassLoader(pluginEnv.getPluginClassLoader());
+ RecipeParseResults results = facet.parseRecipe(recipe);
+ return results;
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
}
}
\ No newline at end of file
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
index 90aab2f..20fa204 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
@@ -187,9 +187,8 @@ public class TestBundleServerPluginService extends ServerPluginService
implement
}
@Override
- public BundleServerPluginFacet getBundleServerPluginFacet(String bundleTypeName)
{
-
- return new TestBundlePluginComponent();
+ public RecipeParseResults parseRecipe(String bundleTypeName, String recipe)
throws Exception {
+ return new TestBundlePluginComponent().parseRecipe(recipe);
}
}